From a0223274b97e82fe02730fd45729172511fec459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Thu, 16 Jun 2016 14:19:39 +0200 Subject: [PATCH 0001/1326] Discard reconfigured CTFont if URL changes Fixes https://github.com/behdad/harfbuzz/issues/267 --- src/hb-coretext.cc | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index e64d2651a..98592af84 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -145,6 +145,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); return NULL; } + CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute); /* Create font copy with cascade list that has LastResort first; this speeds up CoreText * font fallback which we don't need anyway. */ @@ -154,14 +155,31 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) CFRelease (last_resort_font_desc); if (new_ct_font) { - CFRelease (ct_font); - ct_font = new_ct_font; + // The CTFontCreateCopyWithAttributes call fails to stay on the same font + // when reconfiguring the cascade list and may switch to a different font + // when there are fonts that go by the same name, since the descriptor is + // just name and size. + + // Avoid reconfiguring the cascade lists if the new font is outside the + // system locations that we cannot access from the sandboxed renderer + // process in Blink. This can be detected by the new file URL location + // that the newly found font points to. + CFURLRef new_url = (CFURLRef)CTFontCopyAttribute(new_ct_font, kCTFontURLAttribute); + if (CFEqual(original_url, new_url)) { + CFRelease (ct_font); + ct_font = new_ct_font; + } else { + CFRelease(new_ct_font); + DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed."); + } + CFRelease(new_url); } else DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); } - return ct_font; + CFRelease(original_url); + return ct_font; } struct hb_coretext_shaper_face_data_t { From 6b861dbd8b3662d0fa0e51fad1736d72192da868 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 21 Jun 2016 13:57:26 +0430 Subject: [PATCH 0002/1326] [dwrite] Use stream font loader instead GDI interop With help of https://dxr.mozilla.org/mozilla-central/source/gfx/2d/NativeFontResourceDWrite.cpp --- src/hb-directwrite.cc | 378 +++++++++++++++++------------------------- src/hb-directwrite.h | 2 +- 2 files changed, 149 insertions(+), 231 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 96d1870a0..f273f51b8 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -45,176 +45,172 @@ HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face) HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font) + +/* + * DirectWrite font stream helpers + */ + +// This is a font loader which provides only one font (unlike its original design). +// For a better implementation which was also source of this +// and DWriteFontFileStream, have a look at to NativeFontResourceDWrite.cpp in Mozilla +class DWriteFontFileLoader : public IDWriteFontFileLoader +{ +private: + IDWriteFontFileStream *mFontFileStream; +public: + DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream) { + mFontFileStream = fontFileStream; + } + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // IDWriteFontFileLoader methods + virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + OUT IDWriteFontFileStream** fontFileStream) + { + *fontFileStream = mFontFileStream; + return S_OK; + } +}; + +class DWriteFontFileStream : public IDWriteFontFileStream +{ +private: + uint8_t *mData; + uint32_t mSize; +public: + DWriteFontFileStream(uint8_t *aData, uint32_t aSize) + { + mData = aData; + mSize = aSize; + } + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) { return S_OK; } + IFACEMETHOD_(ULONG, AddRef)() { return 1; } + IFACEMETHOD_(ULONG, Release)() { return 1; } + + // IDWriteFontFileStream methods + virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + OUT void** fragmentContext) + { + // We are required to do bounds checking. + if (fileOffset + fragmentSize > mSize) { + return E_FAIL; + } + + // truncate the 64 bit fileOffset to size_t sized index into mData + size_t index = static_cast (fileOffset); + + // We should be alive for the duration of this. + *fragmentStart = &mData[index]; + *fragmentContext = nullptr; + return S_OK; + } + + virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext) { } + + virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize) + { + *fileSize = mSize; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime) + { + return E_NOTIMPL; + } +}; + + /* * shaper face data */ struct hb_directwrite_shaper_face_data_t { - HANDLE fh; - wchar_t face_name[LF_FACESIZE]; + IDWriteFactory* dwriteFactory; + IDWriteFontFile* fontFile; + IDWriteFontFileLoader* fontFileLoader; + IDWriteFontFace* fontFace; }; -/* face_name should point to a wchar_t[LF_FACESIZE] object. */ -static void -_hb_generate_unique_face_name(wchar_t *face_name, unsigned int *plen) -{ - /* We'll create a private name for the font from a UUID using a simple, - * somewhat base64-like encoding scheme */ - const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; - UUID id; - UuidCreate ((UUID*)&id); - ASSERT_STATIC (2 + 3 * (16 / 2) < LF_FACESIZE); - unsigned int name_str_len = 0; - face_name[name_str_len++] = 'F'; - face_name[name_str_len++] = '_'; - unsigned char *p = (unsigned char *)&id; - for (unsigned int i = 0; i < 16; i += 2) - { - /* Spread the 16 bits from two bytes of the UUID across three chars of face_name, - * using the bits in groups of 5,5,6 to select chars from enc. - * This will generate 24 characters; with the 'F_' prefix we already provided, - * the name will be 26 chars (plus the NUL terminator), so will always fit within - * face_name (LF_FACESIZE = 32). */ - face_name[name_str_len++] = enc[p[i] >> 3]; - face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f]; - face_name[name_str_len++] = enc[p[i + 1] & 0x3f]; - } - face_name[name_str_len] = 0; - if (plen) - *plen = name_str_len; -} - -/* Destroys blob. */ -static hb_blob_t * -_hb_rename_font(hb_blob_t *blob, wchar_t *new_name) -{ - /* Create a copy of the font data, with the 'name' table replaced by a - * table that names the font with our private F_* name created above. - * For simplicity, we just append a new 'name' table and update the - * sfnt directory; the original table is left in place, but unused. - * - * The new table will contain just 5 name IDs: family, style, unique, - * full, PS. All of them point to the same name data with our unique name. - */ - - blob = OT::Sanitizer::sanitize (blob); - - unsigned int length, new_length, name_str_len; - const char *orig_sfnt_data = hb_blob_get_data (blob, &length); - - _hb_generate_unique_face_name (new_name, &name_str_len); - - static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 }; - - unsigned int name_table_length = OT::name::min_size + - ARRAY_LENGTH(name_IDs) * OT::NameRecord::static_size + - name_str_len * 2; /* for name data in UTF16BE form */ - unsigned int name_table_offset = (length + 3) & ~3; - - new_length = name_table_offset + ((name_table_length + 3) & ~3); - void *new_sfnt_data = calloc(1, new_length); - if (!new_sfnt_data) - { - hb_blob_destroy (blob); - return NULL; - } - - memcpy(new_sfnt_data, orig_sfnt_data, length); - - OT::name &name = OT::StructAtOffset (new_sfnt_data, name_table_offset); - name.format.set (0); - name.count.set (ARRAY_LENGTH (name_IDs)); - name.stringOffset.set (name.get_size()); - for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++) - { - OT::NameRecord &record = name.nameRecord[i]; - record.platformID.set(3); - record.encodingID.set(1); - record.languageID.set(0x0409u); /* English */ - record.nameID.set(name_IDs[i]); - record.length.set(name_str_len * 2); - record.offset.set(0); - } - - /* Copy string data from new_name, converting wchar_t to UTF16BE. */ - unsigned char *p = &OT::StructAfter(name); - for (unsigned int i = 0; i < name_str_len; i++) - { - *p++ = new_name[i] >> 8; - *p++ = new_name[i] & 0xff; - } - - /* Adjust name table entry to point to new name table */ - const OT::OpenTypeFontFile &file = *(OT::OpenTypeFontFile *) (new_sfnt_data); - unsigned int face_count = file.get_face_count (); - for (unsigned int face_index = 0; face_index < face_count; face_index++) - { - /* Note: doing multiple edits (ie. TTC) can be unsafe. There may be - * toe-stepping. But we don't really care. */ - const OT::OpenTypeFontFace &face = file.get_face (face_index); - unsigned int index; - if (face.find_table_index (HB_OT_TAG_name, &index)) - { - OT::TableRecord &record = const_cast (face.get_table (index)); - record.checkSum.set_for_data (&name, name_table_length); - record.offset.set (name_table_offset); - record.length.set (name_table_length); - } - else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */ - { - free (new_sfnt_data); - hb_blob_destroy (blob); - return NULL; - } - } - - /* The checkSumAdjustment field in the 'head' table is now wrong, - * but that doesn't actually seem to cause any problems so we don't - * bother. */ - - hb_blob_destroy (blob); - return hb_blob_create ((const char *)new_sfnt_data, new_length, - HB_MEMORY_MODE_WRITABLE, NULL, free); -} - hb_directwrite_shaper_face_data_t * _hb_directwrite_shaper_face_data_create(hb_face_t *face) { hb_directwrite_shaper_face_data_t *data = - (hb_directwrite_shaper_face_data_t *) calloc (1, sizeof (hb_directwrite_shaper_face_data_t)); + (hb_directwrite_shaper_face_data_t *) malloc (sizeof (hb_directwrite_shaper_face_data_t)); if (unlikely (!data)) return NULL; - hb_blob_t *blob = hb_face_reference_blob (face); - if (unlikely (!hb_blob_get_length (blob))) - DEBUG_MSG(DIRECTWRITE, face, "Face has empty blob"); + // TODO: factory and fontFileLoader should be cached separately + IDWriteFactory* dwriteFactory; + DWriteCreateFactory ( + DWRITE_FACTORY_TYPE_SHARED, + __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory + ); - blob = _hb_rename_font (blob, data->face_name); - if (unlikely (!blob)) - { - free(data); - return NULL; + + HRESULT hr; + hb_blob_t* blob = hb_face_reference_blob (face); + IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream ( + (uint8_t*) hb_blob_get_data (blob, NULL), hb_blob_get_length (blob)); + + IDWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream); + dwriteFactory->RegisterFontFileLoader (fontFileLoader); + + IDWriteFontFile *fontFile; + uint64_t fontFileKey = 0; + hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey), + fontFileLoader, &fontFile); + +#define FAIL(...) \ + HB_STMT_START { \ + DEBUG_MSG (DIRECTWRITE, NULL, __VA_ARGS__); \ + return false; \ + } HB_STMT_END; + + if (FAILED (hr)) { + FAIL ("Failed to load font file from data!"); + return false; } - DWORD num_fonts_installed; - data->fh = AddFontMemResourceEx ((void *)hb_blob_get_data(blob, NULL), - hb_blob_get_length (blob), - 0, &num_fonts_installed); - if (unlikely (!data->fh)) - { - DEBUG_MSG (DIRECTWRITE, face, "Face AddFontMemResourceEx() failed"); - free (data); - return NULL; + BOOL isSupported; + DWRITE_FONT_FILE_TYPE fileType; + DWRITE_FONT_FACE_TYPE faceType; + UINT32 numberOfFaces; + hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces); + if (FAILED (hr) || !isSupported) { + FAIL ("Font file is not supported."); + return false; } +#undef FAIL + + IDWriteFontFace *fontFace; + dwriteFactory->CreateFontFace (faceType, 1, &fontFile, 0, + DWRITE_FONT_SIMULATIONS_NONE, &fontFace); + + data->dwriteFactory = dwriteFactory; + data->fontFile = fontFile; + data->fontFileLoader = fontFileLoader; + data->fontFace = fontFace; + return data; } void _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) { - RemoveFontMemResourceEx(data->fh); - free(data); + data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); + delete data->fontFileLoader; + free (data); } @@ -223,90 +219,27 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data */ struct hb_directwrite_shaper_font_data_t { - HDC hdc; - LOGFONTW log_font; - HFONT hfont; }; -static bool -populate_log_font (LOGFONTW *lf, - hb_font_t *font) -{ - memset (lf, 0, sizeof (*lf)); - lf->lfHeight = -font->y_scale; - lf->lfCharSet = DEFAULT_CHARSET; - - hb_face_t *face = font->face; - hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - - memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName)); - - return true; -} - hb_directwrite_shaper_font_data_t * _hb_directwrite_shaper_font_data_create (hb_font_t *font) { if (unlikely (!hb_directwrite_shaper_face_data_ensure (font->face))) return NULL; hb_directwrite_shaper_font_data_t *data = - (hb_directwrite_shaper_font_data_t *) calloc (1, sizeof (hb_directwrite_shaper_font_data_t)); + (hb_directwrite_shaper_font_data_t *) malloc (sizeof (hb_directwrite_shaper_font_data_t)); if (unlikely (!data)) return NULL; - data->hdc = GetDC (NULL); - - if (unlikely (!populate_log_font (&data->log_font, font))) - { - DEBUG_MSG (DIRECTWRITE, font, "Font populate_log_font() failed"); - _hb_directwrite_shaper_font_data_destroy (data); - return NULL; - } - - data->hfont = CreateFontIndirectW (&data->log_font); - if (unlikely (!data->hfont)) - { - DEBUG_MSG (DIRECTWRITE, font, "Font CreateFontIndirectW() failed"); - _hb_directwrite_shaper_font_data_destroy (data); - return NULL; - } - - if (!SelectObject (data->hdc, data->hfont)) - { - DEBUG_MSG (DIRECTWRITE, font, "Font SelectObject() failed"); - _hb_directwrite_shaper_font_data_destroy (data); - return NULL; - } - return data; } void _hb_directwrite_shaper_font_data_destroy (hb_directwrite_shaper_font_data_t *data) { - if (data->hdc) - ReleaseDC (NULL, data->hdc); - if (data->hfont) - DeleteObject (data->hfont); free (data); } -LOGFONTW * -hb_directwrite_font_get_logfontw (hb_font_t *font) -{ - if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; - hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); - return &font_data->log_font; -} - -HFONT -hb_directwrite_font_get_hfont (hb_font_t *font) -{ - if (unlikely (!hb_directwrite_shaper_font_data_ensure (font))) return NULL; - hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); - return font_data->hfont; -} - /* * shaper shape_plan data @@ -327,7 +260,7 @@ _hb_directwrite_shaper_shape_plan_data_destroy (hb_directwrite_shaper_shape_plan { } -// Most of here TextAnalysis is originally written by Bas Schouten for Mozilla project +// Most of TextAnalysis is originally written by Bas Schouten for Mozilla project // but now is relicensed to MIT for HarfBuzz use class TextAnalysis : public IDWriteTextAnalysisSource, public IDWriteTextAnalysisSink @@ -581,9 +514,9 @@ protected: Run mRunHead; }; -static inline uint16_t hb_uint16_swap (const uint16_t v) +static inline uint16_t hb_uint16_swap(const uint16_t v) { return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap (const uint32_t v) +static inline uint32_t hb_uint32_swap(const uint32_t v) { return (hb_uint16_swap(v) << 16) | hb_uint16_swap(v >> 16); } /* @@ -600,23 +533,8 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, hb_face_t *face = font->face; hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); hb_directwrite_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); - - // factory probably should be cached -#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION - IDWriteFactory* dwriteFactory; -#else - IDWriteFactory1* dwriteFactory; -#endif - DWriteCreateFactory ( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory - ); - - IDWriteGdiInterop *gdiInterop; - dwriteFactory->GetGdiInterop (&gdiInterop); - IDWriteFontFace* fontFace; - gdiInterop->CreateFontFaceFromHdc (font_data->hdc, &fontFace); + IDWriteFactory *dwriteFactory = face_data->dwriteFactory; + IDWriteFontFace *fontFace = face_data->fontFace; #ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION IDWriteTextAnalyzer* analyzer; @@ -672,7 +590,6 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, } } - HRESULT hr; // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES DWRITE_READING_DIRECTION readingDirection = buffer->props.direction ? @@ -688,6 +605,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, TextAnalysis analysis(textString, textLength, NULL, readingDirection); TextAnalysis::Run *runHead; + HRESULT hr; hr = analysis.GenerateResults(analyzer, &runHead); #define FAIL(...) \ diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h index adf33dfe9..0e1b4799d 100644 --- a/src/hb-directwrite.h +++ b/src/hb-directwrite.h @@ -31,4 +31,4 @@ HB_BEGIN_DECLS HB_END_DECLS -#endif /* HB_UNISCRIBE_H */ +#endif /* HB_DIRECTWRITE_H */ From f3f0ea980a359343ac0e3d359a95855c2cf7be25 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 23 Jun 2016 16:41:37 +0430 Subject: [PATCH 0003/1326] [dwrite] Remove ifdefs without breaking execution on old Windows versions --- src/hb-directwrite.cc | 209 +++++++++++++++++++++--------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index f273f51b8..c6fac4d30 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -25,11 +25,7 @@ #define HB_SHAPER directwrite #include "hb-shaper-impl-private.hh" -#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION - #include -#else - #include -#endif +#include #include "hb-directwrite.h" @@ -156,7 +152,6 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face) (IUnknown**) &dwriteFactory ); - HRESULT hr; hb_blob_t* blob = hb_face_reference_blob (face); IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream ( @@ -377,7 +372,8 @@ public: IFACEMETHODIMP GetLocaleName(uint32_t textPosition, uint32_t* textLength, - wchar_t const** localeName) { + wchar_t const** localeName) + { return S_OK; } @@ -402,7 +398,8 @@ public: { SetCurrentRun(textPosition); SplitCurrentRun(textPosition); - while (textLength > 0) { + while (textLength > 0) + { Run *run = FetchNextRun(&textLength); run->mScript = *scriptAnalysis; } @@ -435,10 +432,12 @@ protected: Run *origRun = mCurrentRun; // Split the tail if needed (the length remaining is less than the // current run's size). - if (*textLength < mCurrentRun->mTextLength) { - SplitCurrentRun(mCurrentRun->mTextStart + *textLength); + if (*textLength < mCurrentRun->mTextLength) + { + SplitCurrentRun (mCurrentRun->mTextStart + *textLength); } - else { + else + { // Just advance the current run. mCurrentRun = mCurrentRun->nextRun; } @@ -455,12 +454,14 @@ protected: // this will usually just return early. If not, find the // corresponding run for the text position. - if (mCurrentRun && mCurrentRun->ContainsTextPosition(textPosition)) { + if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition)) + { return; } for (Run *run = &mRunHead; run; run = run->nextRun) { - if (run->ContainsTextPosition(textPosition)) { + if (run->ContainsTextPosition (textPosition)) + { mCurrentRun = run; return; } @@ -471,13 +472,15 @@ protected: void SplitCurrentRun(uint32_t splitPosition) { - if (!mCurrentRun) { + if (!mCurrentRun) + { //NS_ASSERTION(false, "SplitCurrentRun called without current run."); // Shouldn't be calling this when no current run is set! return; } // Split the current run. - if (splitPosition <= mCurrentRun->mTextStart) { + if (splitPosition <= mCurrentRun->mTextStart) + { // No need to split, already the start of a run // or before it. Usually the first. return; @@ -514,9 +517,9 @@ protected: Run mRunHead; }; -static inline uint16_t hb_uint16_swap(const uint16_t v) +static inline uint16_t hb_uint16_swap (const uint16_t v) { return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap(const uint32_t v) +static inline uint32_t hb_uint32_swap (const uint32_t v) { return (hb_uint16_swap(v) << 16) | hb_uint16_swap(v >> 16); } /* @@ -536,14 +539,8 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, IDWriteFactory *dwriteFactory = face_data->dwriteFactory; IDWriteFontFace *fontFace = face_data->fontFace; -#ifndef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION IDWriteTextAnalyzer* analyzer; dwriteFactory->CreateTextAnalyzer(&analyzer); -#else - IDWriteTextAnalyzer* analyzer0; - dwriteFactory->CreateTextAnalyzer (&analyzer0); - IDWriteTextAnalyzer1* analyzer = (IDWriteTextAnalyzer1*) analyzer0; -#endif unsigned int scratch_size; hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); @@ -717,106 +714,110 @@ retry_getglyphs: return false; } -#ifdef HB_DIRECTWRITE_EXPERIMENTAL_JUSTIFICATION - - DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities = - (DWRITE_JUSTIFICATION_OPPORTUNITY*) - malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY)); - hr = analyzer->GetJustificationOpportunities (fontFace, fontEmSize, - runHead->mScript, textLength, glyphCount, textString, clusterMap, - glyphProperties, justificationOpportunities); - - if (FAILED (hr)) - { - FAIL ("Analyzer failed to get justification opportunities."); - return false; - } - // TODO: get lineWith from somewhere - float lineWidth = 60000; + float lineWidth = 0; - float* justifiedGlyphAdvances = - (float*) malloc (maxGlyphCount * sizeof (float)); - DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) - malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET)); - hr = analyzer->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities, - glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets); + IDWriteTextAnalyzer1* analyzer1; + analyzer->QueryInterface (&analyzer1); - if (FAILED (hr)) + if (analyzer1 && lineWidth) { - FAIL ("Analyzer failed to get justified glyph advances."); - return false; - } - DWRITE_SCRIPT_PROPERTIES scriptProperties; - hr = analyzer->GetScriptProperties (runHead->mScript, &scriptProperties); - if (FAILED (hr)) - { - FAIL ("Analyzer failed to get script properties."); - return false; - } - uint32_t justificationCharacter = scriptProperties.justificationCharacter; + DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities = + (DWRITE_JUSTIFICATION_OPPORTUNITY*) + malloc (maxGlyphCount * sizeof (DWRITE_JUSTIFICATION_OPPORTUNITY)); + hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize, + runHead->mScript, textLength, glyphCount, textString, clusterMap, + glyphProperties, justificationOpportunities); - // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs - if (justificationCharacter != 32) - { -retry_getjustifiedglyphs: - uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); - uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); - float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float)); - DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) - malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET)); - uint32_t actualGlyphsCount; - hr = analyzer->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript, + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get justification opportunities."); + return false; + } + + float* justifiedGlyphAdvances = + (float*) malloc (maxGlyphCount * sizeof (float)); + DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) + malloc (glyphCount * sizeof (DWRITE_GLYPH_OFFSET)); + hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities, + glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets); + + if (FAILED (hr)) + { + FAIL("Analyzer failed to get justified glyph advances."); + return false; + } + + DWRITE_SCRIPT_PROPERTIES scriptProperties; + hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties); + if (FAILED (hr)) + { + FAIL("Analyzer failed to get script properties."); + return false; + } + uint32_t justificationCharacter = scriptProperties.justificationCharacter; + + // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs + if (justificationCharacter != 32) + { + retry_getjustifiedglyphs: + uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof(uint16_t)); + uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof(uint16_t)); + float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof(float)); + DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) + malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET)); + uint32_t actualGlyphsCount; + hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript, textLength, glyphCount, maxGlyphCount, clusterMap, glyphIndices, glyphAdvances, justifiedGlyphAdvances, justifiedGlyphOffsets, glyphProperties, &actualGlyphsCount, modifiedClusterMap, modifiedGlyphIndices, modifiedGlyphAdvances, modifiedGlyphOffsets); - if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)) - { - maxGlyphCount = actualGlyphsCount; - free (modifiedClusterMap); - free (modifiedGlyphIndices); - free (modifiedGlyphAdvances); - free (modifiedGlyphOffsets); + if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)) + { + maxGlyphCount = actualGlyphsCount; + free (modifiedClusterMap); + free (modifiedGlyphIndices); + free (modifiedGlyphAdvances); + free (modifiedGlyphOffsets); - maxGlyphCount = actualGlyphsCount; + maxGlyphCount = actualGlyphsCount; - goto retry_getjustifiedglyphs; + goto retry_getjustifiedglyphs; + } + if (FAILED (hr)) + { + FAIL ("Analyzer failed to get justified glyphs."); + return false; + } + + free (clusterMap); + free (glyphIndices); + free (glyphAdvances); + free (glyphOffsets); + + glyphCount = actualGlyphsCount; + clusterMap = modifiedClusterMap; + glyphIndices = modifiedGlyphIndices; + glyphAdvances = modifiedGlyphAdvances; + glyphOffsets = modifiedGlyphOffsets; + + free (justifiedGlyphAdvances); + free (justifiedGlyphOffsets); } - if (FAILED (hr)) + else { - FAIL ("Analyzer failed to get justified glyphs."); - return false; + free (glyphAdvances); + free (glyphOffsets); + + glyphAdvances = justifiedGlyphAdvances; + glyphOffsets = justifiedGlyphOffsets; } - free (clusterMap); - free (glyphIndices); - free (glyphAdvances); - free (glyphOffsets); + free (justificationOpportunities); - glyphCount = actualGlyphsCount; - clusterMap = modifiedClusterMap; - glyphIndices = modifiedGlyphIndices; - glyphAdvances = modifiedGlyphAdvances; - glyphOffsets = modifiedGlyphOffsets; - - free(justifiedGlyphAdvances); - free(justifiedGlyphOffsets); } - else - { - free(glyphAdvances); - free(glyphOffsets); - - glyphAdvances = justifiedGlyphAdvances; - glyphOffsets = justifiedGlyphOffsets; - } - - free(justificationOpportunities); - -#endif /* Ok, we've got everything we need, now compose output buffer, * very, *very*, carefully! */ From be565d17141818e006aa1e4582f3ae14c726fa85 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 24 Jun 2016 11:42:01 +0430 Subject: [PATCH 0004/1326] [dwrite] Release allocated blob on face destroy This reduces memory consumption of my iterated font create/destroy cycle test significantly and makes it much better than uniscribe backend even --- src/hb-directwrite.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index c6fac4d30..a74e31833 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -134,6 +134,7 @@ struct hb_directwrite_shaper_face_data_t { IDWriteFontFile* fontFile; IDWriteFontFileLoader* fontFileLoader; IDWriteFontFace* fontFace; + hb_blob_t* faceBlob; }; hb_directwrite_shaper_face_data_t * @@ -153,7 +154,7 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face) ); HRESULT hr; - hb_blob_t* blob = hb_face_reference_blob (face); + hb_blob_t *blob = hb_face_reference_blob (face); IDWriteFontFileStream *fontFileStream = new DWriteFontFileStream ( (uint8_t*) hb_blob_get_data (blob, NULL), hb_blob_get_length (blob)); @@ -196,6 +197,7 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face) data->fontFile = fontFile; data->fontFileLoader = fontFileLoader; data->fontFace = fontFace; + data->faceBlob = blob; return data; } @@ -205,6 +207,7 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data { data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); delete data->fontFileLoader; + hb_blob_destroy (data->faceBlob); free (data); } From 07b724f3419a28c479cd8a75ae0eecb841a6d2f3 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 24 Jun 2016 12:23:25 +0430 Subject: [PATCH 0005/1326] [dwrite] Delete remained objects No longer noticeable memory increase on create/destroy iterations, highly better than current state of uniscribe backend --- src/hb-directwrite.cc | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index a74e31833..36b4d5d98 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -130,11 +130,12 @@ public: */ struct hb_directwrite_shaper_face_data_t { - IDWriteFactory* dwriteFactory; - IDWriteFontFile* fontFile; - IDWriteFontFileLoader* fontFileLoader; - IDWriteFontFace* fontFace; - hb_blob_t* faceBlob; + IDWriteFactory *dwriteFactory; + IDWriteFontFile *fontFile; + IDWriteFontFileStream *fontFileStream; + IDWriteFontFileLoader *fontFileLoader; + IDWriteFontFace *fontFace; + hb_blob_t *faceBlob; }; hb_directwrite_shaper_face_data_t * @@ -195,6 +196,7 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face) data->dwriteFactory = dwriteFactory; data->fontFile = fontFile; + data->fontFileStream = fontFileStream; data->fontFileLoader = fontFileLoader; data->fontFace = fontFace; data->faceBlob = blob; @@ -205,10 +207,23 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face) void _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data) { - data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); - delete data->fontFileLoader; - hb_blob_destroy (data->faceBlob); - free (data); + if (data->fontFace) + data->fontFace->Release (); + if (data->fontFile) + data->fontFile->Release (); + if (data->dwriteFactory) { + if (data->fontFileLoader) + data->dwriteFactory->UnregisterFontFileLoader(data->fontFileLoader); + data->dwriteFactory->Release(); + } + if (data->fontFileLoader) + delete data->fontFileLoader; + if (data->fontFileStream) + delete data->fontFileStream; + if (data->faceBlob) + hb_blob_destroy (data->faceBlob); + if (data) + free (data); } From 8179ff5d7ba4a140cf6743729a22072800e98a79 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Mon, 27 Jun 2016 03:54:15 +0430 Subject: [PATCH 0006/1326] [dwrite] Don't allocate more than needed Addressing Nikolay Sivov reviews on harfbuzz mailing list --- src/hb-directwrite.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 36b4d5d98..09889d04e 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -664,11 +664,11 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, (const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures; const uint32_t featureRangeLengths[] = { textLength }; -retry_getglyphs: - uint16_t* clusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); - uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); + uint16_t* clusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t)); DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = (DWRITE_SHAPING_TEXT_PROPERTIES*) - malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES)); + malloc (textLength * sizeof (DWRITE_SHAPING_TEXT_PROPERTIES)); +retry_getglyphs: + uint16_t* glyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES)); @@ -679,9 +679,7 @@ retry_getglyphs: if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))) { - free (clusterMap); free (glyphIndices); - free (textProperties); free (glyphProperties); maxGlyphCount *= 2; @@ -779,10 +777,10 @@ retry_getglyphs: // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs if (justificationCharacter != 32) { + uint16_t* modifiedClusterMap = (uint16_t*) malloc (textLength * sizeof (uint16_t)); retry_getjustifiedglyphs: - uint16_t* modifiedClusterMap = (uint16_t*) malloc (maxGlyphCount * sizeof(uint16_t)); - uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof(uint16_t)); - float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof(float)); + uint16_t* modifiedGlyphIndices = (uint16_t*) malloc (maxGlyphCount * sizeof (uint16_t)); + float* modifiedGlyphAdvances = (float*) malloc (maxGlyphCount * sizeof (float)); DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = (DWRITE_GLYPH_OFFSET*) malloc (maxGlyphCount * sizeof (DWRITE_GLYPH_OFFSET)); uint32_t actualGlyphsCount; @@ -795,7 +793,6 @@ retry_getglyphs: if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)) { maxGlyphCount = actualGlyphsCount; - free (modifiedClusterMap); free (modifiedGlyphIndices); free (modifiedGlyphAdvances); free (modifiedGlyphOffsets); From ae9054c740631e36b7582b44c5afb42ff4509461 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 28 Jun 2016 21:14:38 -0700 Subject: [PATCH 0007/1326] Revert "use utf32" --- src/sample.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sample.py b/src/sample.py index cfbc12265..19a4fdcbc 100755 --- a/src/sample.py +++ b/src/sample.py @@ -20,7 +20,6 @@ def tounicode(s, encoding='utf-8'): fontdata = open (sys.argv[1], 'rb').read () text = tounicode(sys.argv[2]) -codepoints = list(map(ord, text)) # Need to create GLib.Bytes explicitly until this bug is fixed: # https://bugzilla.gnome.org/show_bug.cgi?id=729541 blob = hb.glib_blob_create (GLib.Bytes.new (fontdata)) @@ -40,7 +39,7 @@ class Debugger(object): return True debugger = Debugger() hb.buffer_set_message_func (buf, debugger.message, 1, 0) -hb.buffer_add_utf32 (buf, codepoints, 0, len(codepoints)) +hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) hb.buffer_guess_segment_properties (buf) hb.shape (font, buf, []) From 70e72e5f61d73c33d3c8f3bf07f5a9afd0db046a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 28 Jun 2016 21:00:37 -0700 Subject: [PATCH 0008/1326] [gobject] Fix a few warnings Part of https://github.com/behdad/harfbuzz/issues/277 --- src/hb-buffer.cc | 2 +- src/hb-gobject-structs.h | 12 ++++++++++++ src/hb-shape.cc | 2 -- src/hb-unicode.h | 15 --------------- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 406db9c84..4552d15cd 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -52,7 +52,7 @@ * * Checks the equality of two #hb_segment_properties_t's. * - * Return value: (transfer full): + * Return value: * %true if all properties of @a equal those of @b, false otherwise. * * Since: 0.9.7 diff --git a/src/hb-gobject-structs.h b/src/hb-gobject-structs.h index 0ea3b12cf..1c303219b 100644 --- a/src/hb-gobject-structs.h +++ b/src/hb-gobject-structs.h @@ -41,30 +41,40 @@ HB_BEGIN_DECLS /* Object types */ /** + * hb_gobject_blob_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_blob_get_type (void); #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) /** + * hb_gobject_buffer_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) /** + * hb_gobject_face_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) /** + * hb_gobject_font_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_font_get_type (void); #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) /** + * hb_gobject_font_funcs_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_font_funcs_get_type (void); @@ -77,6 +87,8 @@ HB_EXTERN GType hb_gobject_shape_plan_get_type (void); #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) /** + * hb_gobject_unicode_funcs_get_type: + * * Since: 0.9.2 **/ HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 352d42c83..41a4fc500 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -394,8 +394,6 @@ hb_shape_full (hb_font_t *font, * positioned glyphs. If @features is not %NULL, it will be used to control the * features applied during shaping. * - * Return value: %FALSE if all shapers failed, %TRUE otherwise - * * Since: 0.9.2 **/ void diff --git a/src/hb-unicode.h b/src/hb-unicode.h index 6a15cb00c..2657f4813 100644 --- a/src/hb-unicode.h +++ b/src/hb-unicode.h @@ -449,33 +449,18 @@ HB_EXTERN hb_script_t hb_unicode_script (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); -/** - * hb_unicode_compose: - * - * Since: 0.9.2 - **/ HB_EXTERN hb_bool_t hb_unicode_compose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab); -/** - * hb_unicode_decompose: - * - * Since: 0.9.2 - **/ HB_EXTERN hb_bool_t hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b); -/** - * hb_unicode_decompose_compatibility: - * - * Since: 0.9.2 - **/ HB_EXTERN unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t u, From fc9de44a03a97f6e93bd98d804596cb1f9f4b5fd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 30 Jun 2016 09:46:52 -0700 Subject: [PATCH 0009/1326] Comments --- src/hb-coretext.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 98592af84..db6d2aa14 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -155,15 +155,15 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) CFRelease (last_resort_font_desc); if (new_ct_font) { - // The CTFontCreateCopyWithAttributes call fails to stay on the same font - // when reconfiguring the cascade list and may switch to a different font - // when there are fonts that go by the same name, since the descriptor is - // just name and size. - - // Avoid reconfiguring the cascade lists if the new font is outside the - // system locations that we cannot access from the sandboxed renderer - // process in Blink. This can be detected by the new file URL location - // that the newly found font points to. + /* The CTFontCreateCopyWithAttributes call fails to stay on the same font + * when reconfiguring the cascade list and may switch to a different font + * when there are fonts that go by the same name, since the descriptor is + * just name and size. + * + * Avoid reconfiguring the cascade lists if the new font is outside the + * system locations that we cannot access from the sandboxed renderer + * process in Blink. This can be detected by the new file URL location + * that the newly found font points to. */ CFURLRef new_url = (CFURLRef)CTFontCopyAttribute(new_ct_font, kCTFontURLAttribute); if (CFEqual(original_url, new_url)) { CFRelease (ct_font); From d3e2a06b0f2587e913a9c3ff1a20c187f260db80 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 30 Jun 2016 11:01:22 -0700 Subject: [PATCH 0010/1326] [python] Use utf-32 / utf-16 based on build of Python Fixes https://github.com/behdad/harfbuzz/pull/271 --- src/sample.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/sample.py b/src/sample.py index 19a4fdcbc..c2cb94d53 100755 --- a/src/sample.py +++ b/src/sample.py @@ -3,6 +3,7 @@ from __future__ import print_function import sys +import array from gi.repository import HarfBuzz as hb from gi.repository import GLib @@ -39,7 +40,26 @@ class Debugger(object): return True debugger = Debugger() hb.buffer_set_message_func (buf, debugger.message, 1, 0) -hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) + +## +## Add text to buffer +## +# +# See https://github.com/behdad/harfbuzz/pull/271 +# +if False: + # If you do not care about cluster values reflecting Python + # string indices, then this is quickest way to add text to + # buffer: + hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1) + # Otherwise, then following handles both narrow and wide + # Python builds: +elif sys.maxunicode == 0x10FFFF: + hb.buffer_add_utf32 (buf, array.array('I', text.encode('utf-32')), 0, -1) +else: + hb.buffer_add_utf16 (buf, array.array('H', text.encode('utf-16')), 0, -1) + + hb.buffer_guess_segment_properties (buf) hb.shape (font, buf, []) From e4d451ee55a57e1231b4076fcd1e87994f6b9528 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 2 Jul 2016 00:04:57 +0200 Subject: [PATCH 0011/1326] [introspection] Fix hb_tag_from_string annotation --- src/hb-common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index 5ef832c00..3564e4355 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -88,7 +88,7 @@ hb_tag_from_string (const char *str, int len) /** * hb_tag_to_string: * @tag: - * @buf: (array fixed-size=4): + * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t): * * * From 0b8f3ab0220ca4731516313828515f26bb480645 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Mon, 11 Jul 2016 21:57:26 +0200 Subject: [PATCH 0012/1326] clang in MSVC mode doesn't like when we redefine __attribute__ (#283) --- src/hb-private.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-private.hh b/src/hb-private.hh index d58a695c4..c45be6f2f 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -83,7 +83,7 @@ extern "C" void hb_free_impl(void *ptr); #define unlikely(expr) (expr) #endif -#ifndef __GNUC__ +#if !defined(__GNUC__) && !defined(__clang__) #undef __attribute__ #define __attribute__(x) #endif From 6bf9db4f1e1d51f9acb5e37b89caa8f4d275e7ce Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 11 Jul 2016 13:38:23 -0700 Subject: [PATCH 0013/1326] [ft] Fix unsafe cast of FT_Done_Face in hb_ft_{face,font}_create_referenced (#289) Prior to this change the function `FT_Error FT_Done_Face(FT_Face *)` was called through a pointer with the signature `void (void *)` resulting in undefined behaviour. --- src/hb-ft.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 2cad8c264..6c6749c1d 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -89,11 +89,17 @@ _hb_ft_font_create (FT_Face ft_face, bool unref) return ft_font; } +static void +_hb_ft_face_destroy (FT_Face ft_face) +{ + FT_Done_Face (ft_face); +} + static void _hb_ft_font_destroy (hb_ft_font_t *ft_font) { if (ft_font->unref) - FT_Done_Face (ft_font->ft_face); + _hb_ft_face_destroy (ft_font->ft_face); free (ft_font); } @@ -526,7 +532,7 @@ hb_face_t * hb_ft_face_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); + return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); } static void @@ -606,7 +612,7 @@ hb_font_t * hb_ft_font_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); + return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); } From 874421203e0161db2cbfb27be6c039cba57f7c63 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 12 Jul 2016 03:49:21 +0430 Subject: [PATCH 0014/1326] [coretext] Speculative fix for CoreText nullptr access (#288) --- src/hb-coretext.cc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index db6d2aa14..f4d9716e9 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -164,21 +164,25 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * system locations that we cannot access from the sandboxed renderer * process in Blink. This can be detected by the new file URL location * that the newly found font points to. */ - CFURLRef new_url = (CFURLRef)CTFontCopyAttribute(new_ct_font, kCTFontURLAttribute); - if (CFEqual(original_url, new_url)) { + CFURLRef new_url = (CFURLRef) CTFontCopyAttribute (new_ct_font, kCTFontURLAttribute); + // Keep reconfigured font if URL cannot be retrieved (seems to be the case + // on Mac OS 10.12 Sierra), speculative fix for crbug.com/625606 + if (!original_url || !new_url || CFEqual (original_url, new_url)) { CFRelease (ct_font); ct_font = new_ct_font; } else { - CFRelease(new_ct_font); + CFRelease (new_ct_font); DEBUG_MSG (CORETEXT, ct_font, "Discarding reconfigured CTFont, location changed."); } - CFRelease(new_url); + if (new_url) + CFRelease (new_url); } else DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); } - CFRelease(original_url); + if (original_url) + CFRelease (original_url); return ct_font; } From f80c34eb556d12c45c961d6742c289baef58899d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 12 Jul 2016 11:18:26 -0700 Subject: [PATCH 0015/1326] Whitespace --- src/hb-unicode-private.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index 0cb99f0a0..a4d118b6d 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -182,8 +182,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u); case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu); case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu, - 0x202Au, 0x202Eu, - 0x2060u, 0x206Fu); + 0x202Au, 0x202Eu, + 0x2060u, 0x206Fu); case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu; case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u); default: return false; From 6363d7df28dc4307ef1abb9857d14c35e656b85a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 20 Jul 2016 01:43:56 -0700 Subject: [PATCH 0016/1326] Clean up buffer area when rewinding Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=614647 If allocation fails, we might be leaving junk behind. At least clear it up. --- src/hb-buffer.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 4552d15cd..3940a3dbf 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -183,6 +183,12 @@ hb_buffer_t::shift_forward (unsigned int count) if (unlikely (!ensure (len + count))) return false; memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0])); + if (idx + count > len) + { + /* Under memory failure we might expose this area. At least + * clean it up. Oh well... */ + memset (info + len, 0, (idx + count - len) * sizeof (info[0])); + } len += count; idx += count; @@ -426,6 +432,8 @@ hb_buffer_t::move_to (unsigned int i) /* Tricky part: rewinding... */ unsigned int count = out_len - i; + /* This will blow in our face if memory allocation fails later + * in this same lookup... */ if (unlikely (idx < count && !shift_forward (count + 32))) return false; assert (idx >= count); From 34f9aa582c3a03b578c7eae3d2e8860a0bd5cb00 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 20 Jul 2016 02:35:54 -0700 Subject: [PATCH 0017/1326] Implement symbol cmap in ft and ot fonts Fixes https://github.com/behdad/harfbuzz/issues/236 Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=627953 --- src/hb-ft.cc | 27 +++++++++++++++++++++---- src/hb-ot-font.cc | 50 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 6c6749c1d..eaa1311d4 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -70,11 +70,12 @@ struct hb_ft_font_t { FT_Face ft_face; int load_flags; + bool symbol; /* Whether selected cmap is symbol cmap. */ bool unref; /* Whether to destroy ft_face when done. */ }; static hb_ft_font_t * -_hb_ft_font_create (FT_Face ft_face, bool unref) +_hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) { hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); @@ -82,6 +83,7 @@ _hb_ft_font_create (FT_Face ft_face, bool unref) return NULL; ft_font->ft_face = ft_face; + ft_font->symbol = symbol; ft_font->unref = unref; ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; @@ -171,7 +173,21 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); if (unlikely (!g)) - return false; + { + if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + if (!g) + return false; + } + else + return false; + } *glyph = g; return true; @@ -450,9 +466,11 @@ retry: #endif }; + bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL; + hb_font_set_funcs (font, funcs, - _hb_ft_font_create (ft_face, unref), + _hb_ft_font_create (ft_face, symbol, unref), (hb_destroy_func_t) _hb_ft_font_destroy); } @@ -681,7 +699,8 @@ hb_ft_font_set_funcs (hb_font_t *font) return; } - FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); + if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE)) + FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL); FT_Set_Char_Size (ft_face, abs (font->x_scale), abs (font->y_scale), diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 39fc849a9..0b7e31b2d 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -215,6 +215,28 @@ static inline bool get_glyph_from (const void *obj, return typed_obj->get_glyph (codepoint, glyph); } +template +static inline bool get_glyph_from_symbol (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) +{ + const Type *typed_obj = (const Type *) obj; + if (likely (typed_obj->get_glyph (codepoint, glyph))) + return true; + + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + return typed_obj->get_glyph (0xF000u + codepoint, glyph); + } + + return false; +} + struct hb_ot_face_cmap_accelerator_t { hb_cmap_get_glyph_func_t get_glyph_func; @@ -231,6 +253,7 @@ struct hb_ot_face_cmap_accelerator_t const OT::CmapSubtable *subtable = NULL; const OT::CmapSubtableFormat14 *subtable_uvs = NULL; + bool symbol = false; /* 32-bit subtables. */ if (!subtable) subtable = cmap->find_subtable (3, 10); if (!subtable) subtable = cmap->find_subtable (0, 6); @@ -241,7 +264,7 @@ struct hb_ot_face_cmap_accelerator_t if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable) subtable = cmap->find_subtable (3, 0); + if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true); /* Meh. */ if (!subtable) subtable = &OT::Null(OT::CmapSubtable); @@ -258,18 +281,21 @@ struct hb_ot_face_cmap_accelerator_t this->uvs_table = subtable_uvs; this->get_glyph_data = subtable; - switch (subtable->u.format) { - /* Accelerate format 4 and format 12. */ - default: this->get_glyph_func = get_glyph_from; break; - case 12: this->get_glyph_func = get_glyph_from; break; - case 4: - { - this->format4_accel.init (&subtable->u.format4); - this->get_glyph_data = &this->format4_accel; - this->get_glyph_func = this->format4_accel.get_glyph_func; + if (unlikely (symbol)) + this->get_glyph_func = get_glyph_from_symbol; + else + switch (subtable->u.format) { + /* Accelerate format 4 and format 12. */ + default: this->get_glyph_func = get_glyph_from; break; + case 12: this->get_glyph_func = get_glyph_from; break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_func = this->format4_accel.get_glyph_func; + } + break; } - break; - } } inline void fini (void) From f3f6c1ccbf89e15cda03e0c3a2df4297e98adf60 Mon Sep 17 00:00:00 2001 From: jfkthame Date: Thu, 16 Jun 2016 00:10:42 +0100 Subject: [PATCH 0018/1326] Blacklist GDEF tables of more fonts This is based on bug reports that have been filed against Firefox since it updated to a version of harfbuzz that uses zeroing by GDEF rather than by Unicode. I'm sure there are a bunch more font versions that should also be included; these are just the ones I have on hand and have confirmed as having bad GDEF data. Given how the list here is growing, I think we should reconsider the approach, and perhaps revert to zeroing by Unicode instead. Fixes https://github.com/behdad/harfbuzz/issues/264 Fixes https://github.com/behdad/harfbuzz/pull/266 --- src/hb-ot-layout.cc | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 29749bce7..b52c5f37e 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -93,6 +93,45 @@ _hb_ot_layout_create (hb_face_t *face) if (3 == layout->gdef->get_glyph_class (5)) layout->gdef = &OT::Null(OT::GDEF); } + else if (0 + /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ + || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len) + /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ + || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len) + /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ + || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) + /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ + || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) + /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ + || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) + /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ + || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) + /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ + || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) + /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ + || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) + /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ + || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) + /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ + || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len) + /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ + /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ + || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len) + /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ + /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ + || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) + ) + { + /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks + * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya, + * and the version of Cantarell shipped by Ubuntu 16.04. + * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 + */ + layout->gdef = &OT::Null(OT::GDEF); + } } layout->gsub_lookup_count = layout->gsub->get_lookup_count (); From 08c08af2f9ed683ad20322c3ef1ba0f87ce15426 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 21 Jul 2016 01:23:33 -0700 Subject: [PATCH 0019/1326] [ucdn] Update to Unicode 9.0.0 Fixes https://github.com/grigorig/ucdn/issues/12 --- src/hb-ucdn.cc | 6 + src/hb-ucdn/README | 1 - src/hb-ucdn/ucdn.c | 80 +- src/hb-ucdn/ucdn.h | 98 +- src/hb-ucdn/unicodedata_db.h | 4754 +++++++++++++++++++--------------- 5 files changed, 2785 insertions(+), 2154 deletions(-) diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc index b4a583324..a884e3ffd 100644 --- a/src/hb-ucdn.cc +++ b/src/hb-ucdn.cc @@ -154,6 +154,12 @@ static const hb_script_t ucdn_script_translate[] = HB_SCRIPT_MULTANI, HB_SCRIPT_OLD_HUNGARIAN, HB_SCRIPT_SIGNWRITING, + HB_SCRIPT_ADLAM, + HB_SCRIPT_BHAIKSUKI, + HB_SCRIPT_MARCHEN, + HB_SCRIPT_NEWA, + HB_SCRIPT_OSAGE, + HB_SCRIPT_TANGUT, }; static hb_unicode_combining_class_t diff --git a/src/hb-ucdn/README b/src/hb-ucdn/README index 2f3c55296..fcb97b9aa 100644 --- a/src/hb-ucdn/README +++ b/src/hb-ucdn/README @@ -1,7 +1,6 @@ Contents of this directory are derived from UCDN: https://github.com/grigorig/ucdn - https://github.com/behdad/ucdn The original README follows: diff --git a/src/hb-ucdn/ucdn.c b/src/hb-ucdn/ucdn.c index d1a419573..f4e9be17c 100644 --- a/src/hb-ucdn/ucdn.c +++ b/src/hb-ucdn/ucdn.c @@ -16,6 +16,7 @@ #include #include +#include #include "ucdn.h" typedef struct { @@ -24,14 +25,19 @@ typedef struct { unsigned char bidi_class; unsigned char mirrored; unsigned char east_asian_width; - unsigned char normalization_check; unsigned char script; + unsigned char linebreak_class; } UCDRecord; typedef struct { unsigned short from, to; } MirrorPair; +typedef struct { + unsigned short from, to; + unsigned char type; +} BracketPair; + typedef struct { unsigned int start; short count, index; @@ -108,6 +114,24 @@ static int compare_mp(const void *a, const void *b) return mpa->from - mpb->from; } +static int compare_bp(const void *a, const void *b) +{ + BracketPair *bpa = (BracketPair *)a; + BracketPair *bpb = (BracketPair *)b; + return bpa->from - bpb->from; +} + +static BracketPair *search_bp(uint32_t code) +{ + BracketPair bp = {0,0,2}; + BracketPair *res; + + bp.from = code; + res = bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN, sizeof(BracketPair), + compare_bp); + return res; +} + static int hangul_pair_decompose(uint32_t code, uint32_t *a, uint32_t *b) { int si = code - SBASE; @@ -199,6 +223,42 @@ int ucdn_get_script(uint32_t code) return get_ucd_record(code)->script; } +int ucdn_get_linebreak_class(uint32_t code) +{ + return get_ucd_record(code)->linebreak_class; +} + +int ucdn_get_resolved_linebreak_class(uint32_t code) +{ + const UCDRecord *record = get_ucd_record(code); + + switch (record->linebreak_class) + { + case UCDN_LINEBREAK_CLASS_AI: + case UCDN_LINEBREAK_CLASS_SG: + case UCDN_LINEBREAK_CLASS_XX: + return UCDN_LINEBREAK_CLASS_AL; + + case UCDN_LINEBREAK_CLASS_SA: + if (record->category == UCDN_GENERAL_CATEGORY_MC || + record->category == UCDN_GENERAL_CATEGORY_MN) + return UCDN_LINEBREAK_CLASS_CM; + return UCDN_LINEBREAK_CLASS_AL; + + case UCDN_LINEBREAK_CLASS_CJ: + return UCDN_LINEBREAK_CLASS_NS; + + case UCDN_LINEBREAK_CLASS_CB: + return UCDN_LINEBREAK_CLASS_B2; + + case UCDN_LINEBREAK_CLASS_NL: + return UCDN_LINEBREAK_CLASS_BK; + + default: + return record->linebreak_class; + } +} + uint32_t ucdn_mirror(uint32_t code) { MirrorPair mp = {0}; @@ -217,6 +277,24 @@ uint32_t ucdn_mirror(uint32_t code) return res->to; } +uint32_t ucdn_paired_bracket(uint32_t code) +{ + BracketPair *res = search_bp(code); + if (res == NULL) + return code; + else + return res->to; +} + +int ucdn_paired_bracket_type(uint32_t code) +{ + BracketPair *res = search_bp(code); + if (res == NULL) + return UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE; + else + return res->type; +} + int ucdn_decompose(uint32_t code, uint32_t *a, uint32_t *b) { const unsigned short *rec; diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h index 8354ae533..f694dc5a8 100644 --- a/src/hb-ucdn/ucdn.h +++ b/src/hb-ucdn/ucdn.h @@ -17,6 +17,8 @@ #ifndef UCDN_H #define UCDN_H + + #if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) # define HB_BEGIN_VISIBILITY _Pragma ("GCC visibility push(hidden)") # define HB_END_VISIBILITY _Pragma ("GCC visibility pop") @@ -58,6 +60,7 @@ typedef unsigned __int64 uint64_t; #endif + #define UCDN_EAST_ASIAN_F 0 #define UCDN_EAST_ASIAN_H 1 #define UCDN_EAST_ASIAN_W 2 @@ -197,6 +200,53 @@ typedef unsigned __int64 uint64_t; #define UCDN_SCRIPT_MULTANI 129 #define UCDN_SCRIPT_OLD_HUNGARIAN 130 #define UCDN_SCRIPT_SIGNWRITING 131 +#define UCDN_SCRIPT_ADLAM 132 +#define UCDN_SCRIPT_BHAIKSUKI 133 +#define UCDN_SCRIPT_MARCHEN 134 +#define UCDN_SCRIPT_NEWA 135 +#define UCDN_SCRIPT_OSAGE 136 +#define UCDN_SCRIPT_TANGUT 137 + +#define UCDN_LINEBREAK_CLASS_OP 0 +#define UCDN_LINEBREAK_CLASS_CL 1 +#define UCDN_LINEBREAK_CLASS_CP 2 +#define UCDN_LINEBREAK_CLASS_QU 3 +#define UCDN_LINEBREAK_CLASS_GL 4 +#define UCDN_LINEBREAK_CLASS_NS 5 +#define UCDN_LINEBREAK_CLASS_EX 6 +#define UCDN_LINEBREAK_CLASS_SY 7 +#define UCDN_LINEBREAK_CLASS_IS 8 +#define UCDN_LINEBREAK_CLASS_PR 9 +#define UCDN_LINEBREAK_CLASS_PO 10 +#define UCDN_LINEBREAK_CLASS_NU 11 +#define UCDN_LINEBREAK_CLASS_AL 12 +#define UCDN_LINEBREAK_CLASS_HL 13 +#define UCDN_LINEBREAK_CLASS_ID 14 +#define UCDN_LINEBREAK_CLASS_IN 15 +#define UCDN_LINEBREAK_CLASS_HY 16 +#define UCDN_LINEBREAK_CLASS_BA 17 +#define UCDN_LINEBREAK_CLASS_BB 18 +#define UCDN_LINEBREAK_CLASS_B2 19 +#define UCDN_LINEBREAK_CLASS_ZW 20 +#define UCDN_LINEBREAK_CLASS_CM 21 +#define UCDN_LINEBREAK_CLASS_WJ 22 +#define UCDN_LINEBREAK_CLASS_H2 23 +#define UCDN_LINEBREAK_CLASS_H3 24 +#define UCDN_LINEBREAK_CLASS_JL 25 +#define UCDN_LINEBREAK_CLASS_JV 26 +#define UCDN_LINEBREAK_CLASS_JT 27 +#define UCDN_LINEBREAK_CLASS_RI 28 +#define UCDN_LINEBREAK_CLASS_AI 29 +#define UCDN_LINEBREAK_CLASS_BK 30 +#define UCDN_LINEBREAK_CLASS_CB 31 +#define UCDN_LINEBREAK_CLASS_CJ 32 +#define UCDN_LINEBREAK_CLASS_CR 33 +#define UCDN_LINEBREAK_CLASS_LF 34 +#define UCDN_LINEBREAK_CLASS_NL 35 +#define UCDN_LINEBREAK_CLASS_SA 36 +#define UCDN_LINEBREAK_CLASS_SG 37 +#define UCDN_LINEBREAK_CLASS_SP 38 +#define UCDN_LINEBREAK_CLASS_XX 39 #define UCDN_GENERAL_CATEGORY_CC 0 #define UCDN_GENERAL_CATEGORY_CF 1 @@ -253,6 +303,10 @@ typedef unsigned __int64 uint64_t; #define UCDN_BIDI_CLASS_FSI 21 #define UCDN_BIDI_CLASS_PDI 22 +#define UCDN_BIDI_PAIRED_BRACKET_TYPE_OPEN 0 +#define UCDN_BIDI_PAIRED_BRACKET_TYPE_CLOSE 1 +#define UCDN_BIDI_PAIRED_BRACKET_TYPE_NONE 2 + /** * Return version of the Unicode database. * @@ -301,6 +355,27 @@ int ucdn_get_bidi_class(uint32_t code); */ int ucdn_get_script(uint32_t code); +/** + * Get unresolved linebreak class of a codepoint. This does not take + * rule LB1 of UAX#14 into account. See ucdn_get_resolved_linebreak_class() + * for resolved linebreak classes. + * + * @param code Unicode codepoint + * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14. + */ +int ucdn_get_linebreak_class(uint32_t code); + +/** + * Get resolved linebreak class of a codepoint. This resolves characters + * in the AI, SG, XX, SA and CJ classes according to rule LB1 of UAX#14. + * In addition the CB class is resolved as the equivalent B2 class and + * the NL class is resolved as the equivalent BK class. + * + * @param code Unicode codepoint + * @return value according to UCDN_LINEBREAK_* and as defined in UAX#14. + */ +int ucdn_get_resolved_linebreak_class(uint32_t code); + /** * Check if codepoint can be mirrored. * @@ -318,6 +393,25 @@ int ucdn_get_mirrored(uint32_t code); */ uint32_t ucdn_mirror(uint32_t code); +/** + * Get paired bracket for a codepoint. + * + * @param code Unicode codepoint + * @return paired bracket codepoint or the original codepoint if no + * paired bracket character exists + */ +uint32_t ucdn_paired_bracket(uint32_t code); + +/** + * Get paired bracket type for a codepoint. + * + * @param code Unicode codepoint + * @return value according to UCDN_BIDI_PAIRED_BRACKET_TYPE_* and as defined + * in UAX#9. + * + */ +int ucdn_paired_bracket_type(uint32_t code); + /** * Pairwise canonical decomposition of a codepoint. This includes * Hangul Jamo decomposition (see chapter 3.12 of the Unicode core @@ -359,6 +453,8 @@ int ucdn_compat_decompose(uint32_t code, uint32_t *decomposed); */ int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b); -HB_END_HEADER +#ifdef __cplusplus +} +#endif #endif diff --git a/src/hb-ucdn/unicodedata_db.h b/src/hb-ucdn/unicodedata_db.h index f458be14a..c9cd59bc6 100644 --- a/src/hb-ucdn/unicodedata_db.h +++ b/src/hb-ucdn/unicodedata_db.h @@ -1,821 +1,999 @@ /* this file was generated by makeunicodedata.py 3.2 */ -#define UNIDATA_VERSION "8.0.0" +#define UNIDATA_VERSION "9.0.0" /* a list of unique database records */ static const UCDRecord ucd_records[] = { - {2, 0, 18, 0, 5, 0, 102}, - {0, 0, 14, 0, 5, 0, 0}, - {0, 0, 16, 0, 5, 0, 0}, - {0, 0, 15, 0, 5, 0, 0}, - {0, 0, 17, 0, 5, 0, 0}, - {29, 0, 17, 0, 3, 0, 0}, - {21, 0, 18, 0, 3, 0, 0}, - {21, 0, 10, 0, 3, 0, 0}, - {23, 0, 10, 0, 3, 0, 0}, + {2, 0, 18, 0, 5, 102, 41}, + {0, 0, 14, 0, 5, 0, 21}, + {0, 0, 16, 0, 5, 0, 17}, + {0, 0, 15, 0, 5, 0, 35}, + {0, 0, 16, 0, 5, 0, 30}, + {0, 0, 17, 0, 5, 0, 30}, + {0, 0, 15, 0, 5, 0, 33}, + {0, 0, 15, 0, 5, 0, 21}, + {0, 0, 16, 0, 5, 0, 21}, + {29, 0, 17, 0, 3, 0, 40}, + {21, 0, 18, 0, 3, 0, 6}, + {21, 0, 18, 0, 3, 0, 3}, + {21, 0, 10, 0, 3, 0, 12}, + {23, 0, 10, 0, 3, 0, 9}, + {21, 0, 10, 0, 3, 0, 10}, + {21, 0, 18, 0, 3, 0, 12}, {22, 0, 18, 1, 3, 0, 0}, - {18, 0, 18, 1, 3, 0, 0}, - {25, 0, 9, 0, 3, 0, 0}, - {21, 0, 12, 0, 3, 0, 0}, - {17, 0, 9, 0, 3, 0, 0}, - {13, 0, 8, 0, 3, 0, 0}, - {25, 0, 18, 1, 3, 0, 0}, - {25, 0, 18, 0, 3, 0, 0}, - {9, 0, 0, 0, 3, 0, 1}, - {24, 0, 18, 0, 3, 0, 0}, - {16, 0, 18, 0, 3, 0, 0}, - {5, 0, 0, 0, 3, 0, 1}, - {29, 0, 12, 0, 5, 0, 0}, + {18, 0, 18, 1, 3, 0, 2}, + {25, 0, 9, 0, 3, 0, 9}, + {21, 0, 12, 0, 3, 0, 8}, + {17, 0, 9, 0, 3, 0, 16}, + {21, 0, 12, 0, 3, 0, 7}, + {13, 0, 8, 0, 3, 0, 11}, + {21, 0, 18, 0, 3, 0, 8}, + {25, 0, 18, 1, 3, 0, 12}, + {25, 0, 18, 0, 3, 0, 12}, + {9, 0, 0, 0, 3, 1, 12}, + {21, 0, 18, 0, 3, 0, 9}, + {24, 0, 18, 0, 3, 0, 12}, + {16, 0, 18, 0, 3, 0, 12}, + {5, 0, 0, 0, 3, 1, 12}, + {25, 0, 18, 0, 3, 0, 17}, + {18, 0, 18, 1, 3, 0, 1}, + {0, 0, 15, 0, 5, 0, 36}, + {29, 0, 12, 0, 5, 0, 4}, {21, 0, 18, 0, 4, 0, 0}, - {23, 0, 10, 0, 4, 0, 0}, - {26, 0, 18, 0, 3, 0, 0}, - {24, 0, 18, 0, 4, 0, 0}, - {26, 0, 18, 0, 5, 0, 0}, - {7, 0, 0, 0, 4, 0, 1}, - {20, 0, 18, 1, 5, 0, 0}, - {1, 0, 14, 0, 4, 0, 0}, - {26, 0, 18, 0, 4, 0, 0}, - {26, 0, 10, 0, 4, 0, 0}, - {25, 0, 10, 0, 4, 0, 0}, - {15, 0, 8, 0, 4, 0, 0}, - {5, 0, 0, 0, 5, 0, 0}, - {19, 0, 18, 1, 5, 0, 0}, - {15, 0, 18, 0, 4, 0, 0}, - {9, 0, 0, 0, 5, 0, 1}, - {9, 0, 0, 0, 4, 0, 1}, - {25, 0, 18, 0, 4, 0, 0}, - {5, 0, 0, 0, 4, 0, 1}, - {5, 0, 0, 0, 5, 0, 1}, - {7, 0, 0, 0, 5, 0, 1}, - {8, 0, 0, 0, 5, 0, 1}, - {6, 0, 0, 0, 5, 0, 1}, - {6, 0, 18, 0, 5, 0, 0}, - {6, 0, 0, 0, 5, 0, 0}, - {24, 0, 18, 0, 5, 0, 0}, - {6, 0, 18, 0, 4, 0, 0}, - {6, 0, 0, 0, 4, 0, 0}, - {24, 0, 18, 0, 5, 0, 34}, - {12, 230, 13, 0, 4, 0, 40}, - {12, 232, 13, 0, 4, 0, 40}, - {12, 220, 13, 0, 4, 0, 40}, - {12, 216, 13, 0, 4, 0, 40}, - {12, 202, 13, 0, 4, 0, 40}, - {12, 1, 13, 0, 4, 0, 40}, - {12, 240, 13, 0, 4, 0, 40}, - {12, 0, 13, 0, 4, 0, 40}, - {12, 233, 13, 0, 4, 0, 40}, - {12, 234, 13, 0, 4, 0, 40}, - {9, 0, 0, 0, 5, 0, 2}, - {5, 0, 0, 0, 5, 0, 2}, - {24, 0, 18, 0, 5, 0, 2}, - {2, 0, 18, 0, 5, 0, 102}, - {6, 0, 0, 0, 5, 0, 2}, - {21, 0, 18, 0, 5, 0, 0}, - {9, 0, 0, 0, 4, 0, 2}, - {5, 0, 0, 0, 4, 0, 2}, - {9, 0, 0, 0, 5, 0, 54}, - {5, 0, 0, 0, 5, 0, 54}, - {25, 0, 18, 0, 5, 0, 2}, - {9, 0, 0, 0, 5, 0, 3}, - {9, 0, 0, 0, 4, 0, 3}, - {5, 0, 0, 0, 4, 0, 3}, - {5, 0, 0, 0, 5, 0, 3}, - {26, 0, 0, 0, 5, 0, 3}, - {12, 230, 13, 0, 5, 0, 3}, - {12, 230, 13, 0, 5, 0, 40}, - {11, 0, 13, 0, 5, 0, 3}, - {9, 0, 0, 0, 5, 0, 4}, - {6, 0, 0, 0, 5, 0, 4}, - {21, 0, 0, 0, 5, 0, 4}, - {5, 0, 0, 0, 5, 0, 4}, - {21, 0, 0, 0, 5, 0, 0}, - {17, 0, 18, 0, 5, 0, 4}, - {26, 0, 18, 0, 5, 0, 4}, - {23, 0, 10, 0, 5, 0, 4}, - {12, 220, 13, 0, 5, 0, 5}, - {12, 230, 13, 0, 5, 0, 5}, - {12, 222, 13, 0, 5, 0, 5}, - {12, 228, 13, 0, 5, 0, 5}, - {12, 10, 13, 0, 5, 0, 5}, - {12, 11, 13, 0, 5, 0, 5}, - {12, 12, 13, 0, 5, 0, 5}, - {12, 13, 13, 0, 5, 0, 5}, - {12, 14, 13, 0, 5, 0, 5}, - {12, 15, 13, 0, 5, 0, 5}, - {12, 16, 13, 0, 5, 0, 5}, - {12, 17, 13, 0, 5, 0, 5}, - {12, 18, 13, 0, 5, 0, 5}, - {12, 19, 13, 0, 5, 0, 5}, - {12, 20, 13, 0, 5, 0, 5}, - {12, 21, 13, 0, 5, 0, 5}, - {12, 22, 13, 0, 5, 0, 5}, - {17, 0, 3, 0, 5, 0, 5}, - {12, 23, 13, 0, 5, 0, 5}, - {21, 0, 3, 0, 5, 0, 5}, - {12, 24, 13, 0, 5, 0, 5}, - {12, 25, 13, 0, 5, 0, 5}, - {7, 0, 3, 0, 5, 0, 5}, - {1, 0, 11, 0, 5, 0, 6}, - {1, 0, 11, 0, 5, 0, 0}, - {25, 0, 18, 0, 5, 0, 6}, - {25, 0, 4, 0, 5, 0, 6}, - {21, 0, 10, 0, 5, 0, 6}, - {23, 0, 4, 0, 5, 0, 6}, - {21, 0, 12, 0, 5, 0, 0}, + {23, 0, 10, 0, 3, 0, 10}, + {23, 0, 10, 0, 4, 0, 9}, + {26, 0, 18, 0, 3, 0, 12}, + {21, 0, 18, 0, 4, 0, 29}, + {24, 0, 18, 0, 4, 0, 29}, + {26, 0, 18, 0, 5, 0, 12}, + {7, 0, 0, 0, 4, 1, 29}, + {20, 0, 18, 1, 5, 0, 3}, + {1, 0, 14, 0, 4, 0, 17}, + {26, 0, 18, 0, 4, 0, 12}, + {26, 0, 10, 0, 4, 0, 10}, + {25, 0, 10, 0, 4, 0, 9}, + {15, 0, 8, 0, 4, 0, 29}, + {24, 0, 18, 0, 4, 0, 18}, + {5, 0, 0, 0, 5, 0, 12}, + {19, 0, 18, 1, 5, 0, 3}, + {15, 0, 18, 0, 4, 0, 29}, + {9, 0, 0, 0, 5, 1, 12}, + {9, 0, 0, 0, 4, 1, 12}, + {25, 0, 18, 0, 4, 0, 29}, + {5, 0, 0, 0, 4, 1, 12}, + {5, 0, 0, 0, 5, 1, 12}, + {7, 0, 0, 0, 5, 1, 12}, + {8, 0, 0, 0, 5, 1, 12}, + {6, 0, 0, 0, 5, 1, 12}, + {6, 0, 18, 0, 5, 0, 12}, + {6, 0, 0, 0, 5, 0, 12}, + {24, 0, 18, 0, 5, 0, 12}, + {24, 0, 18, 0, 4, 0, 12}, + {6, 0, 18, 0, 4, 0, 29}, + {6, 0, 18, 0, 5, 0, 18}, + {6, 0, 0, 0, 4, 0, 29}, + {24, 0, 18, 0, 5, 34, 12}, + {12, 230, 13, 0, 4, 40, 21}, + {12, 232, 13, 0, 4, 40, 21}, + {12, 220, 13, 0, 4, 40, 21}, + {12, 216, 13, 0, 4, 40, 21}, + {12, 202, 13, 0, 4, 40, 21}, + {12, 1, 13, 0, 4, 40, 21}, + {12, 240, 13, 0, 4, 40, 21}, + {12, 0, 13, 0, 4, 40, 4}, + {12, 233, 13, 0, 4, 40, 4}, + {12, 234, 13, 0, 4, 40, 4}, + {9, 0, 0, 0, 5, 2, 12}, + {5, 0, 0, 0, 5, 2, 12}, + {24, 0, 18, 0, 5, 2, 12}, + {2, 0, 18, 0, 5, 102, 41}, + {6, 0, 0, 0, 5, 2, 12}, + {21, 0, 18, 0, 5, 0, 8}, + {21, 0, 18, 0, 5, 0, 12}, + {9, 0, 0, 0, 4, 2, 12}, + {5, 0, 0, 0, 4, 2, 12}, + {9, 0, 0, 0, 5, 54, 12}, + {5, 0, 0, 0, 5, 54, 12}, + {25, 0, 18, 0, 5, 2, 12}, + {9, 0, 0, 0, 5, 3, 12}, + {9, 0, 0, 0, 4, 3, 12}, + {5, 0, 0, 0, 4, 3, 12}, + {5, 0, 0, 0, 5, 3, 12}, + {26, 0, 0, 0, 5, 3, 12}, + {12, 230, 13, 0, 5, 3, 21}, + {12, 230, 13, 0, 5, 40, 21}, + {11, 0, 13, 0, 5, 3, 21}, + {9, 0, 0, 0, 5, 4, 12}, + {6, 0, 0, 0, 5, 4, 12}, + {21, 0, 0, 0, 5, 4, 12}, + {5, 0, 0, 0, 5, 4, 12}, + {21, 0, 0, 0, 5, 0, 8}, + {17, 0, 18, 0, 5, 4, 17}, + {26, 0, 18, 0, 5, 4, 12}, + {23, 0, 10, 0, 5, 4, 9}, + {12, 220, 13, 0, 5, 5, 21}, + {12, 230, 13, 0, 5, 5, 21}, + {12, 222, 13, 0, 5, 5, 21}, + {12, 228, 13, 0, 5, 5, 21}, + {12, 10, 13, 0, 5, 5, 21}, + {12, 11, 13, 0, 5, 5, 21}, + {12, 12, 13, 0, 5, 5, 21}, + {12, 13, 13, 0, 5, 5, 21}, + {12, 14, 13, 0, 5, 5, 21}, + {12, 15, 13, 0, 5, 5, 21}, + {12, 16, 13, 0, 5, 5, 21}, + {12, 17, 13, 0, 5, 5, 21}, + {12, 18, 13, 0, 5, 5, 21}, + {12, 19, 13, 0, 5, 5, 21}, + {12, 20, 13, 0, 5, 5, 21}, + {12, 21, 13, 0, 5, 5, 21}, + {12, 22, 13, 0, 5, 5, 21}, + {17, 0, 3, 0, 5, 5, 17}, + {12, 23, 13, 0, 5, 5, 21}, + {21, 0, 3, 0, 5, 5, 12}, + {12, 24, 13, 0, 5, 5, 21}, + {12, 25, 13, 0, 5, 5, 21}, + {21, 0, 3, 0, 5, 5, 6}, + {7, 0, 3, 0, 5, 5, 13}, + {1, 0, 11, 0, 5, 6, 12}, + {1, 0, 11, 0, 5, 0, 12}, + {25, 0, 18, 0, 5, 6, 12}, + {25, 0, 4, 0, 5, 6, 12}, + {21, 0, 10, 0, 5, 6, 10}, + {23, 0, 4, 0, 5, 6, 10}, + {21, 0, 12, 0, 5, 0, 8}, + {21, 0, 4, 0, 5, 6, 8}, + {26, 0, 18, 0, 5, 6, 12}, + {12, 230, 13, 0, 5, 6, 21}, + {12, 30, 13, 0, 5, 6, 21}, + {12, 31, 13, 0, 5, 6, 21}, + {12, 32, 13, 0, 5, 6, 21}, {21, 0, 4, 0, 5, 0, 6}, - {26, 0, 18, 0, 5, 0, 6}, - {12, 230, 13, 0, 5, 0, 6}, - {12, 30, 13, 0, 5, 0, 6}, - {12, 31, 13, 0, 5, 0, 6}, - {12, 32, 13, 0, 5, 0, 6}, - {21, 0, 4, 0, 5, 0, 0}, - {1, 0, 4, 0, 5, 0, 0}, - {7, 0, 4, 0, 5, 0, 6}, - {6, 0, 4, 0, 5, 0, 0}, - {12, 27, 13, 0, 5, 0, 40}, - {12, 28, 13, 0, 5, 0, 40}, - {12, 29, 13, 0, 5, 0, 40}, - {12, 30, 13, 0, 5, 0, 40}, - {12, 31, 13, 0, 5, 0, 40}, - {12, 32, 13, 0, 5, 0, 40}, - {12, 33, 13, 0, 5, 0, 40}, - {12, 34, 13, 0, 5, 0, 40}, - {12, 220, 13, 0, 5, 0, 40}, - {12, 220, 13, 0, 5, 0, 6}, - {13, 0, 11, 0, 5, 0, 6}, - {21, 0, 11, 0, 5, 0, 6}, - {12, 35, 13, 0, 5, 0, 40}, - {6, 0, 4, 0, 5, 0, 6}, - {13, 0, 8, 0, 5, 0, 6}, - {26, 0, 4, 0, 5, 0, 6}, - {21, 0, 4, 0, 5, 0, 7}, - {1, 0, 4, 0, 5, 0, 7}, - {7, 0, 4, 0, 5, 0, 7}, - {12, 36, 13, 0, 5, 0, 7}, - {12, 230, 13, 0, 5, 0, 7}, - {12, 220, 13, 0, 5, 0, 7}, - {7, 0, 4, 0, 5, 0, 8}, - {12, 0, 13, 0, 5, 0, 8}, - {13, 0, 3, 0, 5, 0, 65}, - {7, 0, 3, 0, 5, 0, 65}, - {12, 230, 13, 0, 5, 0, 65}, - {12, 220, 13, 0, 5, 0, 65}, - {6, 0, 3, 0, 5, 0, 65}, - {26, 0, 18, 0, 5, 0, 65}, - {21, 0, 18, 0, 5, 0, 65}, - {7, 0, 3, 0, 5, 0, 81}, - {12, 230, 13, 0, 5, 0, 81}, - {6, 0, 3, 0, 5, 0, 81}, - {21, 0, 3, 0, 5, 0, 81}, - {7, 0, 3, 0, 5, 0, 94}, - {12, 220, 13, 0, 5, 0, 94}, - {21, 0, 3, 0, 5, 0, 94}, - {12, 27, 13, 0, 5, 0, 6}, - {12, 28, 13, 0, 5, 0, 6}, - {12, 29, 13, 0, 5, 0, 6}, - {12, 0, 13, 0, 5, 0, 9}, - {10, 0, 0, 0, 5, 0, 9}, - {7, 0, 0, 0, 5, 0, 9}, - {12, 7, 13, 0, 5, 0, 9}, - {12, 9, 13, 0, 5, 0, 9}, - {12, 230, 13, 0, 5, 0, 9}, - {13, 0, 0, 0, 5, 0, 9}, - {21, 0, 0, 0, 5, 0, 9}, - {6, 0, 0, 0, 5, 0, 9}, - {7, 0, 0, 0, 5, 0, 10}, - {12, 0, 13, 0, 5, 0, 10}, - {10, 0, 0, 0, 5, 0, 10}, - {12, 7, 13, 0, 5, 0, 10}, - {12, 9, 13, 0, 5, 0, 10}, - {13, 0, 0, 0, 5, 0, 10}, - {23, 0, 10, 0, 5, 0, 10}, - {15, 0, 0, 0, 5, 0, 10}, - {26, 0, 0, 0, 5, 0, 10}, - {12, 0, 13, 0, 5, 0, 11}, - {10, 0, 0, 0, 5, 0, 11}, - {7, 0, 0, 0, 5, 0, 11}, - {12, 7, 13, 0, 5, 0, 11}, - {12, 9, 13, 0, 5, 0, 11}, - {13, 0, 0, 0, 5, 0, 11}, - {12, 0, 13, 0, 5, 0, 12}, - {10, 0, 0, 0, 5, 0, 12}, - {7, 0, 0, 0, 5, 0, 12}, - {12, 7, 13, 0, 5, 0, 12}, - {12, 9, 13, 0, 5, 0, 12}, - {13, 0, 0, 0, 5, 0, 12}, + {1, 0, 4, 0, 5, 0, 21}, + {21, 0, 4, 0, 5, 6, 6}, + {7, 0, 4, 0, 5, 6, 12}, + {6, 0, 4, 0, 5, 0, 12}, + {12, 27, 13, 0, 5, 40, 21}, + {12, 28, 13, 0, 5, 40, 21}, + {12, 29, 13, 0, 5, 40, 21}, + {12, 30, 13, 0, 5, 40, 21}, + {12, 31, 13, 0, 5, 40, 21}, + {12, 32, 13, 0, 5, 40, 21}, + {12, 33, 13, 0, 5, 40, 21}, + {12, 34, 13, 0, 5, 40, 21}, + {12, 220, 13, 0, 5, 40, 21}, + {12, 220, 13, 0, 5, 6, 21}, + {13, 0, 11, 0, 5, 6, 11}, + {21, 0, 11, 0, 5, 6, 11}, + {21, 0, 4, 0, 5, 6, 12}, + {12, 35, 13, 0, 5, 40, 21}, + {6, 0, 4, 0, 5, 6, 12}, + {13, 0, 8, 0, 5, 6, 11}, + {26, 0, 4, 0, 5, 6, 12}, + {21, 0, 4, 0, 5, 7, 12}, + {1, 0, 4, 0, 5, 7, 12}, + {7, 0, 4, 0, 5, 7, 12}, + {12, 36, 13, 0, 5, 7, 21}, + {12, 230, 13, 0, 5, 7, 21}, + {12, 220, 13, 0, 5, 7, 21}, + {7, 0, 4, 0, 5, 8, 12}, + {12, 0, 13, 0, 5, 8, 21}, + {13, 0, 3, 0, 5, 65, 11}, + {7, 0, 3, 0, 5, 65, 12}, + {12, 230, 13, 0, 5, 65, 21}, + {12, 220, 13, 0, 5, 65, 21}, + {6, 0, 3, 0, 5, 65, 12}, + {26, 0, 18, 0, 5, 65, 12}, + {21, 0, 18, 0, 5, 65, 12}, + {21, 0, 18, 0, 5, 65, 8}, + {21, 0, 18, 0, 5, 65, 6}, + {7, 0, 3, 0, 5, 81, 12}, + {12, 230, 13, 0, 5, 81, 21}, + {6, 0, 3, 0, 5, 81, 12}, + {21, 0, 3, 0, 5, 81, 12}, + {7, 0, 3, 0, 5, 94, 12}, + {12, 220, 13, 0, 5, 94, 21}, + {21, 0, 3, 0, 5, 94, 12}, + {12, 27, 13, 0, 5, 6, 21}, + {12, 28, 13, 0, 5, 6, 21}, + {12, 29, 13, 0, 5, 6, 21}, + {12, 0, 13, 0, 5, 9, 21}, + {10, 0, 0, 0, 5, 9, 21}, + {7, 0, 0, 0, 5, 9, 12}, + {12, 7, 13, 0, 5, 9, 21}, + {12, 9, 13, 0, 5, 9, 21}, + {12, 230, 13, 0, 5, 9, 21}, + {21, 0, 0, 0, 5, 0, 17}, + {13, 0, 0, 0, 5, 9, 11}, + {21, 0, 0, 0, 5, 9, 12}, + {6, 0, 0, 0, 5, 9, 12}, + {7, 0, 0, 0, 5, 10, 12}, + {12, 0, 13, 0, 5, 10, 21}, + {10, 0, 0, 0, 5, 10, 21}, + {12, 7, 13, 0, 5, 10, 21}, + {12, 9, 13, 0, 5, 10, 21}, + {13, 0, 0, 0, 5, 10, 11}, + {23, 0, 10, 0, 5, 10, 10}, + {15, 0, 0, 0, 5, 10, 12}, + {15, 0, 0, 0, 5, 10, 10}, + {26, 0, 0, 0, 5, 10, 12}, + {23, 0, 10, 0, 5, 10, 9}, + {12, 0, 13, 0, 5, 11, 21}, + {10, 0, 0, 0, 5, 11, 21}, + {7, 0, 0, 0, 5, 11, 12}, + {12, 7, 13, 0, 5, 11, 21}, + {12, 9, 13, 0, 5, 11, 21}, + {13, 0, 0, 0, 5, 11, 11}, + {12, 0, 13, 0, 5, 12, 21}, + {10, 0, 0, 0, 5, 12, 21}, + {7, 0, 0, 0, 5, 12, 12}, + {12, 7, 13, 0, 5, 12, 21}, + {12, 9, 13, 0, 5, 12, 21}, + {13, 0, 0, 0, 5, 12, 11}, + {21, 0, 0, 0, 5, 12, 12}, + {23, 0, 10, 0, 5, 12, 9}, + {12, 0, 13, 0, 5, 13, 21}, + {10, 0, 0, 0, 5, 13, 21}, + {7, 0, 0, 0, 5, 13, 12}, + {12, 7, 13, 0, 5, 13, 21}, + {12, 9, 13, 0, 5, 13, 21}, + {13, 0, 0, 0, 5, 13, 11}, + {26, 0, 0, 0, 5, 13, 12}, + {15, 0, 0, 0, 5, 13, 12}, + {12, 0, 13, 0, 5, 14, 21}, + {7, 0, 0, 0, 5, 14, 12}, + {10, 0, 0, 0, 5, 14, 21}, + {12, 9, 13, 0, 5, 14, 21}, + {13, 0, 0, 0, 5, 14, 11}, + {15, 0, 0, 0, 5, 14, 12}, + {26, 0, 18, 0, 5, 14, 12}, + {23, 0, 10, 0, 5, 14, 9}, + {12, 0, 13, 0, 5, 15, 21}, + {10, 0, 0, 0, 5, 15, 21}, + {7, 0, 0, 0, 5, 15, 12}, + {12, 9, 13, 0, 5, 15, 21}, + {12, 84, 13, 0, 5, 15, 21}, + {12, 91, 13, 0, 5, 15, 21}, + {13, 0, 0, 0, 5, 15, 11}, + {15, 0, 18, 0, 5, 15, 12}, + {26, 0, 0, 0, 5, 15, 12}, + {7, 0, 0, 0, 5, 16, 12}, + {12, 0, 13, 0, 5, 16, 21}, + {10, 0, 0, 0, 5, 16, 21}, + {12, 7, 13, 0, 5, 16, 21}, + {12, 0, 0, 0, 5, 16, 21}, + {12, 9, 13, 0, 5, 16, 21}, + {13, 0, 0, 0, 5, 16, 11}, + {12, 0, 13, 0, 5, 17, 21}, + {10, 0, 0, 0, 5, 17, 21}, + {7, 0, 0, 0, 5, 17, 12}, + {12, 9, 13, 0, 5, 17, 21}, + {26, 0, 0, 0, 5, 17, 12}, + {15, 0, 0, 0, 5, 17, 12}, + {13, 0, 0, 0, 5, 17, 11}, + {26, 0, 0, 0, 5, 17, 10}, + {10, 0, 0, 0, 5, 18, 21}, + {7, 0, 0, 0, 5, 18, 12}, + {12, 9, 13, 0, 5, 18, 21}, + {12, 0, 13, 0, 5, 18, 21}, + {13, 0, 0, 0, 5, 18, 11}, + {21, 0, 0, 0, 5, 18, 12}, + {7, 0, 0, 0, 5, 19, 38}, + {12, 0, 13, 0, 5, 19, 38}, + {12, 103, 13, 0, 5, 19, 38}, + {12, 9, 13, 0, 5, 19, 38}, + {23, 0, 10, 0, 5, 0, 9}, + {6, 0, 0, 0, 5, 19, 38}, + {12, 107, 13, 0, 5, 19, 38}, + {21, 0, 0, 0, 5, 19, 12}, + {13, 0, 0, 0, 5, 19, 11}, + {21, 0, 0, 0, 5, 19, 17}, + {7, 0, 0, 0, 5, 20, 38}, + {12, 0, 13, 0, 5, 20, 38}, + {12, 118, 13, 0, 5, 20, 38}, + {6, 0, 0, 0, 5, 20, 38}, + {12, 122, 13, 0, 5, 20, 38}, + {13, 0, 0, 0, 5, 20, 11}, + {7, 0, 0, 0, 5, 21, 12}, + {26, 0, 0, 0, 5, 21, 18}, + {21, 0, 0, 0, 5, 21, 18}, + {21, 0, 0, 0, 5, 21, 12}, + {21, 0, 0, 0, 5, 21, 4}, + {21, 0, 0, 0, 5, 21, 17}, + {21, 0, 0, 0, 5, 21, 6}, + {26, 0, 0, 0, 5, 21, 12}, + {12, 220, 13, 0, 5, 21, 21}, + {13, 0, 0, 0, 5, 21, 11}, + {15, 0, 0, 0, 5, 21, 12}, + {26, 0, 0, 0, 5, 21, 17}, + {12, 216, 13, 0, 5, 21, 21}, + {22, 0, 18, 1, 5, 21, 0}, + {18, 0, 18, 1, 5, 21, 1}, + {10, 0, 0, 0, 5, 21, 21}, + {12, 129, 13, 0, 5, 21, 21}, + {12, 130, 13, 0, 5, 21, 21}, + {12, 0, 13, 0, 5, 21, 21}, + {12, 132, 13, 0, 5, 21, 21}, + {10, 0, 0, 0, 5, 21, 17}, + {12, 230, 13, 0, 5, 21, 21}, + {12, 9, 13, 0, 5, 21, 21}, + {26, 0, 0, 0, 5, 0, 12}, + {7, 0, 0, 0, 5, 22, 38}, + {10, 0, 0, 0, 5, 22, 38}, + {12, 0, 13, 0, 5, 22, 38}, + {12, 7, 13, 0, 5, 22, 38}, + {12, 9, 13, 0, 5, 22, 38}, + {13, 0, 0, 0, 5, 22, 11}, + {21, 0, 0, 0, 5, 22, 17}, + {21, 0, 0, 0, 5, 22, 12}, + {12, 220, 13, 0, 5, 22, 38}, + {26, 0, 0, 0, 5, 22, 38}, + {9, 0, 0, 0, 5, 23, 12}, + {7, 0, 0, 0, 5, 23, 12}, {21, 0, 0, 0, 5, 0, 12}, - {23, 0, 10, 0, 5, 0, 12}, - {12, 0, 13, 0, 5, 0, 13}, - {10, 0, 0, 0, 5, 0, 13}, - {7, 0, 0, 0, 5, 0, 13}, - {12, 7, 13, 0, 5, 0, 13}, - {12, 9, 13, 0, 5, 0, 13}, - {13, 0, 0, 0, 5, 0, 13}, - {26, 0, 0, 0, 5, 0, 13}, - {15, 0, 0, 0, 5, 0, 13}, - {12, 0, 13, 0, 5, 0, 14}, - {7, 0, 0, 0, 5, 0, 14}, - {10, 0, 0, 0, 5, 0, 14}, - {12, 9, 13, 0, 5, 0, 14}, - {13, 0, 0, 0, 5, 0, 14}, - {15, 0, 0, 0, 5, 0, 14}, - {26, 0, 18, 0, 5, 0, 14}, - {23, 0, 10, 0, 5, 0, 14}, - {12, 0, 13, 0, 5, 0, 15}, - {10, 0, 0, 0, 5, 0, 15}, - {7, 0, 0, 0, 5, 0, 15}, - {12, 9, 13, 0, 5, 0, 15}, - {12, 84, 13, 0, 5, 0, 15}, - {12, 91, 13, 0, 5, 0, 15}, - {13, 0, 0, 0, 5, 0, 15}, - {15, 0, 18, 0, 5, 0, 15}, - {26, 0, 0, 0, 5, 0, 15}, - {12, 0, 13, 0, 5, 0, 16}, - {10, 0, 0, 0, 5, 0, 16}, - {7, 0, 0, 0, 5, 0, 16}, - {12, 7, 13, 0, 5, 0, 16}, - {12, 0, 0, 0, 5, 0, 16}, - {12, 9, 13, 0, 5, 0, 16}, - {13, 0, 0, 0, 5, 0, 16}, - {12, 0, 13, 0, 5, 0, 17}, - {10, 0, 0, 0, 5, 0, 17}, - {7, 0, 0, 0, 5, 0, 17}, - {12, 9, 13, 0, 5, 0, 17}, - {13, 0, 0, 0, 5, 0, 17}, - {15, 0, 0, 0, 5, 0, 17}, - {26, 0, 0, 0, 5, 0, 17}, - {10, 0, 0, 0, 5, 0, 18}, - {7, 0, 0, 0, 5, 0, 18}, - {12, 9, 13, 0, 5, 0, 18}, - {12, 0, 13, 0, 5, 0, 18}, - {13, 0, 0, 0, 5, 0, 18}, - {21, 0, 0, 0, 5, 0, 18}, - {7, 0, 0, 0, 5, 0, 19}, - {12, 0, 13, 0, 5, 0, 19}, - {12, 103, 13, 0, 5, 0, 19}, - {12, 9, 13, 0, 5, 0, 19}, - {23, 0, 10, 0, 5, 0, 0}, - {6, 0, 0, 0, 5, 0, 19}, - {12, 107, 13, 0, 5, 0, 19}, - {21, 0, 0, 0, 5, 0, 19}, - {13, 0, 0, 0, 5, 0, 19}, - {7, 0, 0, 0, 5, 0, 20}, - {12, 0, 13, 0, 5, 0, 20}, - {12, 118, 13, 0, 5, 0, 20}, - {6, 0, 0, 0, 5, 0, 20}, - {12, 122, 13, 0, 5, 0, 20}, - {13, 0, 0, 0, 5, 0, 20}, - {7, 0, 0, 0, 5, 0, 21}, - {26, 0, 0, 0, 5, 0, 21}, - {21, 0, 0, 0, 5, 0, 21}, - {12, 220, 13, 0, 5, 0, 21}, - {13, 0, 0, 0, 5, 0, 21}, - {15, 0, 0, 0, 5, 0, 21}, - {12, 216, 13, 0, 5, 0, 21}, - {22, 0, 18, 1, 5, 0, 21}, - {18, 0, 18, 1, 5, 0, 21}, + {6, 0, 0, 0, 5, 23, 12}, + {7, 0, 0, 0, 2, 24, 25}, + {7, 0, 0, 0, 5, 24, 26}, + {7, 0, 0, 0, 5, 24, 27}, + {7, 0, 0, 0, 5, 25, 12}, + {12, 230, 13, 0, 5, 25, 21}, + {21, 0, 0, 0, 5, 25, 12}, + {21, 0, 0, 0, 5, 25, 17}, + {15, 0, 0, 0, 5, 25, 12}, + {26, 0, 18, 0, 5, 25, 12}, + {9, 0, 0, 0, 5, 26, 12}, + {5, 0, 0, 0, 5, 26, 12}, + {17, 0, 18, 0, 5, 27, 17}, + {7, 0, 0, 0, 5, 27, 12}, + {21, 0, 0, 0, 5, 27, 12}, + {29, 0, 17, 0, 5, 28, 17}, + {7, 0, 0, 0, 5, 28, 12}, + {22, 0, 18, 1, 5, 28, 0}, + {18, 0, 18, 1, 5, 28, 1}, + {7, 0, 0, 0, 5, 29, 12}, + {14, 0, 0, 0, 5, 29, 12}, + {7, 0, 0, 0, 5, 41, 12}, + {12, 0, 13, 0, 5, 41, 21}, + {12, 9, 13, 0, 5, 41, 21}, + {7, 0, 0, 0, 5, 42, 12}, + {12, 0, 13, 0, 5, 42, 21}, + {12, 9, 13, 0, 5, 42, 21}, + {7, 0, 0, 0, 5, 43, 12}, + {12, 0, 13, 0, 5, 43, 21}, + {7, 0, 0, 0, 5, 44, 12}, + {12, 0, 13, 0, 5, 44, 21}, + {7, 0, 0, 0, 5, 30, 38}, + {12, 0, 13, 0, 5, 30, 38}, + {10, 0, 0, 0, 5, 30, 38}, + {12, 9, 13, 0, 5, 30, 38}, + {21, 0, 0, 0, 5, 30, 17}, + {21, 0, 0, 0, 5, 30, 5}, + {6, 0, 0, 0, 5, 30, 38}, + {21, 0, 0, 0, 5, 30, 12}, + {23, 0, 10, 0, 5, 30, 9}, + {12, 230, 13, 0, 5, 30, 38}, + {13, 0, 0, 0, 5, 30, 11}, + {15, 0, 18, 0, 5, 30, 12}, + {21, 0, 18, 0, 5, 31, 12}, + {21, 0, 18, 0, 5, 0, 6}, + {21, 0, 18, 0, 5, 31, 17}, + {21, 0, 18, 0, 5, 0, 17}, + {17, 0, 18, 0, 5, 31, 18}, + {21, 0, 18, 0, 5, 31, 6}, + {12, 0, 13, 0, 5, 31, 21}, + {1, 0, 14, 0, 5, 31, 4}, + {13, 0, 0, 0, 5, 31, 11}, + {7, 0, 0, 0, 5, 31, 12}, + {6, 0, 0, 0, 5, 31, 12}, + {12, 228, 13, 0, 5, 31, 21}, + {7, 0, 0, 0, 5, 45, 12}, + {12, 0, 13, 0, 5, 45, 21}, + {10, 0, 0, 0, 5, 45, 21}, + {12, 222, 13, 0, 5, 45, 21}, + {12, 230, 13, 0, 5, 45, 21}, + {12, 220, 13, 0, 5, 45, 21}, + {26, 0, 18, 0, 5, 45, 12}, + {21, 0, 18, 0, 5, 45, 6}, + {13, 0, 0, 0, 5, 45, 11}, + {7, 0, 0, 0, 5, 46, 38}, + {7, 0, 0, 0, 5, 55, 38}, + {13, 0, 0, 0, 5, 55, 11}, + {15, 0, 0, 0, 5, 55, 38}, + {26, 0, 18, 0, 5, 55, 38}, + {26, 0, 18, 0, 5, 30, 12}, + {7, 0, 0, 0, 5, 53, 12}, + {12, 230, 13, 0, 5, 53, 21}, + {12, 220, 13, 0, 5, 53, 21}, + {10, 0, 0, 0, 5, 53, 21}, + {12, 0, 13, 0, 5, 53, 21}, + {21, 0, 0, 0, 5, 53, 12}, + {7, 0, 0, 0, 5, 77, 38}, + {10, 0, 0, 0, 5, 77, 38}, + {12, 0, 13, 0, 5, 77, 38}, + {12, 9, 13, 0, 5, 77, 38}, + {12, 230, 13, 0, 5, 77, 38}, + {12, 220, 13, 0, 5, 77, 21}, + {13, 0, 0, 0, 5, 77, 11}, + {21, 0, 0, 0, 5, 77, 38}, + {6, 0, 0, 0, 5, 77, 38}, + {11, 0, 13, 0, 5, 40, 21}, + {12, 0, 13, 0, 5, 61, 21}, + {10, 0, 0, 0, 5, 61, 21}, + {7, 0, 0, 0, 5, 61, 12}, + {12, 7, 13, 0, 5, 61, 21}, + {10, 9, 0, 0, 5, 61, 21}, + {13, 0, 0, 0, 5, 61, 11}, + {21, 0, 0, 0, 5, 61, 17}, + {21, 0, 0, 0, 5, 61, 12}, + {26, 0, 0, 0, 5, 61, 12}, + {12, 230, 13, 0, 5, 61, 21}, + {12, 220, 13, 0, 5, 61, 21}, + {12, 0, 13, 0, 5, 66, 21}, + {10, 0, 0, 0, 5, 66, 21}, + {7, 0, 0, 0, 5, 66, 12}, + {10, 9, 0, 0, 5, 66, 21}, + {12, 9, 13, 0, 5, 66, 21}, + {13, 0, 0, 0, 5, 66, 11}, + {7, 0, 0, 0, 5, 92, 12}, + {12, 7, 13, 0, 5, 92, 21}, + {10, 0, 0, 0, 5, 92, 21}, + {12, 0, 13, 0, 5, 92, 21}, + {10, 9, 0, 0, 5, 92, 21}, + {21, 0, 0, 0, 5, 92, 12}, + {7, 0, 0, 0, 5, 67, 12}, + {10, 0, 0, 0, 5, 67, 21}, + {12, 0, 13, 0, 5, 67, 21}, + {12, 7, 13, 0, 5, 67, 21}, + {21, 0, 0, 0, 5, 67, 17}, + {13, 0, 0, 0, 5, 67, 11}, + {13, 0, 0, 0, 5, 68, 11}, + {7, 0, 0, 0, 5, 68, 12}, + {6, 0, 0, 0, 5, 68, 12}, + {21, 0, 0, 0, 5, 68, 17}, + {21, 0, 0, 0, 5, 66, 12}, + {12, 1, 13, 0, 5, 40, 21}, {10, 0, 0, 0, 5, 0, 21}, - {12, 129, 13, 0, 5, 0, 21}, - {12, 130, 13, 0, 5, 0, 21}, - {12, 0, 13, 0, 5, 0, 21}, - {12, 132, 13, 0, 5, 0, 21}, - {12, 230, 13, 0, 5, 0, 21}, - {12, 9, 13, 0, 5, 0, 21}, - {26, 0, 0, 0, 5, 0, 0}, - {7, 0, 0, 0, 5, 0, 22}, - {10, 0, 0, 0, 5, 0, 22}, - {12, 0, 13, 0, 5, 0, 22}, - {12, 7, 13, 0, 5, 0, 22}, - {12, 9, 13, 0, 5, 0, 22}, - {13, 0, 0, 0, 5, 0, 22}, - {21, 0, 0, 0, 5, 0, 22}, - {12, 220, 13, 0, 5, 0, 22}, - {26, 0, 0, 0, 5, 0, 22}, - {9, 0, 0, 0, 5, 0, 23}, - {7, 0, 0, 0, 5, 0, 23}, - {6, 0, 0, 0, 5, 0, 23}, - {7, 0, 0, 0, 2, 0, 24}, - {7, 0, 0, 0, 5, 0, 24}, - {7, 0, 0, 0, 5, 0, 25}, - {12, 230, 13, 0, 5, 0, 25}, - {21, 0, 0, 0, 5, 0, 25}, - {15, 0, 0, 0, 5, 0, 25}, - {26, 0, 18, 0, 5, 0, 25}, - {9, 0, 0, 0, 5, 0, 26}, - {5, 0, 0, 0, 5, 0, 26}, - {17, 0, 18, 0, 5, 0, 27}, - {7, 0, 0, 0, 5, 0, 27}, - {21, 0, 0, 0, 5, 0, 27}, - {29, 0, 17, 0, 5, 0, 28}, - {7, 0, 0, 0, 5, 0, 28}, - {22, 0, 18, 1, 5, 0, 28}, - {18, 0, 18, 1, 5, 0, 28}, - {7, 0, 0, 0, 5, 0, 29}, - {14, 0, 0, 0, 5, 0, 29}, - {7, 0, 0, 0, 5, 0, 41}, - {12, 0, 13, 0, 5, 0, 41}, - {12, 9, 13, 0, 5, 0, 41}, - {7, 0, 0, 0, 5, 0, 42}, - {12, 0, 13, 0, 5, 0, 42}, - {12, 9, 13, 0, 5, 0, 42}, - {7, 0, 0, 0, 5, 0, 43}, - {12, 0, 13, 0, 5, 0, 43}, - {7, 0, 0, 0, 5, 0, 44}, - {12, 0, 13, 0, 5, 0, 44}, - {7, 0, 0, 0, 5, 0, 30}, - {12, 0, 13, 0, 5, 0, 30}, - {10, 0, 0, 0, 5, 0, 30}, - {12, 9, 13, 0, 5, 0, 30}, - {21, 0, 0, 0, 5, 0, 30}, - {6, 0, 0, 0, 5, 0, 30}, - {23, 0, 10, 0, 5, 0, 30}, - {12, 230, 13, 0, 5, 0, 30}, - {13, 0, 0, 0, 5, 0, 30}, - {15, 0, 18, 0, 5, 0, 30}, - {21, 0, 18, 0, 5, 0, 31}, - {17, 0, 18, 0, 5, 0, 31}, - {12, 0, 13, 0, 5, 0, 31}, - {1, 0, 14, 0, 5, 0, 31}, - {13, 0, 0, 0, 5, 0, 31}, - {7, 0, 0, 0, 5, 0, 31}, - {6, 0, 0, 0, 5, 0, 31}, - {12, 228, 13, 0, 5, 0, 31}, - {7, 0, 0, 0, 5, 0, 45}, - {12, 0, 13, 0, 5, 0, 45}, - {10, 0, 0, 0, 5, 0, 45}, - {12, 222, 13, 0, 5, 0, 45}, - {12, 230, 13, 0, 5, 0, 45}, - {12, 220, 13, 0, 5, 0, 45}, - {26, 0, 18, 0, 5, 0, 45}, - {21, 0, 18, 0, 5, 0, 45}, - {13, 0, 0, 0, 5, 0, 45}, - {7, 0, 0, 0, 5, 0, 46}, - {7, 0, 0, 0, 5, 0, 55}, - {13, 0, 0, 0, 5, 0, 55}, - {15, 0, 0, 0, 5, 0, 55}, - {26, 0, 18, 0, 5, 0, 55}, - {26, 0, 18, 0, 5, 0, 30}, - {7, 0, 0, 0, 5, 0, 53}, - {12, 230, 13, 0, 5, 0, 53}, - {12, 220, 13, 0, 5, 0, 53}, - {10, 0, 0, 0, 5, 0, 53}, - {12, 0, 13, 0, 5, 0, 53}, - {21, 0, 0, 0, 5, 0, 53}, - {7, 0, 0, 0, 5, 0, 77}, - {10, 0, 0, 0, 5, 0, 77}, - {12, 0, 13, 0, 5, 0, 77}, - {12, 9, 13, 0, 5, 0, 77}, - {12, 230, 13, 0, 5, 0, 77}, - {12, 220, 13, 0, 5, 0, 77}, - {13, 0, 0, 0, 5, 0, 77}, - {21, 0, 0, 0, 5, 0, 77}, - {6, 0, 0, 0, 5, 0, 77}, - {11, 0, 13, 0, 5, 0, 40}, - {12, 0, 13, 0, 5, 0, 61}, - {10, 0, 0, 0, 5, 0, 61}, - {7, 0, 0, 0, 5, 0, 61}, - {12, 7, 13, 0, 5, 0, 61}, - {10, 9, 0, 0, 5, 0, 61}, - {13, 0, 0, 0, 5, 0, 61}, - {21, 0, 0, 0, 5, 0, 61}, - {26, 0, 0, 0, 5, 0, 61}, - {12, 230, 13, 0, 5, 0, 61}, - {12, 220, 13, 0, 5, 0, 61}, - {12, 0, 13, 0, 5, 0, 66}, - {10, 0, 0, 0, 5, 0, 66}, - {7, 0, 0, 0, 5, 0, 66}, - {10, 9, 0, 0, 5, 0, 66}, - {12, 9, 13, 0, 5, 0, 66}, - {13, 0, 0, 0, 5, 0, 66}, - {7, 0, 0, 0, 5, 0, 92}, - {12, 7, 13, 0, 5, 0, 92}, - {10, 0, 0, 0, 5, 0, 92}, - {12, 0, 13, 0, 5, 0, 92}, - {10, 9, 0, 0, 5, 0, 92}, - {21, 0, 0, 0, 5, 0, 92}, - {7, 0, 0, 0, 5, 0, 67}, - {10, 0, 0, 0, 5, 0, 67}, - {12, 0, 13, 0, 5, 0, 67}, - {12, 7, 13, 0, 5, 0, 67}, - {21, 0, 0, 0, 5, 0, 67}, - {13, 0, 0, 0, 5, 0, 67}, - {13, 0, 0, 0, 5, 0, 68}, - {7, 0, 0, 0, 5, 0, 68}, - {6, 0, 0, 0, 5, 0, 68}, - {21, 0, 0, 0, 5, 0, 68}, - {21, 0, 0, 0, 5, 0, 66}, - {12, 1, 13, 0, 5, 0, 40}, - {10, 0, 0, 0, 5, 0, 0}, - {7, 0, 0, 0, 5, 0, 0}, - {6, 0, 0, 0, 5, 0, 3}, - {12, 234, 13, 0, 5, 0, 40}, - {12, 214, 13, 0, 5, 0, 40}, - {12, 202, 13, 0, 5, 0, 40}, - {12, 233, 13, 0, 5, 0, 40}, - {8, 0, 0, 0, 5, 0, 2}, - {29, 0, 17, 0, 5, 0, 0}, - {1, 0, 14, 0, 5, 0, 0}, - {1, 0, 14, 0, 5, 0, 40}, - {1, 0, 0, 0, 5, 0, 0}, - {1, 0, 3, 0, 5, 0, 0}, - {17, 0, 18, 0, 4, 0, 0}, - {17, 0, 18, 0, 5, 0, 0}, - {20, 0, 18, 0, 4, 0, 0}, - {19, 0, 18, 0, 4, 0, 0}, + {7, 0, 0, 0, 5, 0, 12}, + {6, 0, 0, 0, 5, 3, 12}, + {12, 234, 13, 0, 5, 40, 21}, + {12, 214, 13, 0, 5, 40, 21}, + {12, 202, 13, 0, 5, 40, 21}, + {12, 233, 13, 0, 5, 40, 21}, + {8, 0, 0, 0, 5, 2, 12}, + {24, 0, 18, 0, 5, 2, 18}, + {29, 0, 17, 0, 5, 0, 17}, + {29, 0, 17, 0, 5, 0, 4}, + {1, 0, 14, 0, 5, 0, 20}, + {1, 0, 14, 0, 5, 40, 21}, + {1, 0, 14, 0, 5, 40, 41}, + {1, 0, 0, 0, 5, 0, 21}, + {1, 0, 3, 0, 5, 0, 21}, + {17, 0, 18, 0, 4, 0, 17}, + {17, 0, 18, 0, 5, 0, 4}, + {17, 0, 18, 0, 5, 0, 17}, + {17, 0, 18, 0, 4, 0, 19}, + {17, 0, 18, 0, 4, 0, 29}, + {20, 0, 18, 0, 4, 0, 3}, + {19, 0, 18, 0, 4, 0, 3}, {22, 0, 18, 0, 5, 0, 0}, - {20, 0, 18, 0, 5, 0, 0}, - {27, 0, 17, 0, 5, 0, 0}, - {28, 0, 15, 0, 5, 0, 0}, - {1, 0, 1, 0, 5, 0, 0}, - {1, 0, 5, 0, 5, 0, 0}, - {1, 0, 7, 0, 5, 0, 0}, - {1, 0, 2, 0, 5, 0, 0}, - {1, 0, 6, 0, 5, 0, 0}, - {21, 0, 10, 0, 4, 0, 0}, - {21, 0, 10, 0, 5, 0, 0}, - {16, 0, 18, 0, 5, 0, 0}, - {25, 0, 12, 0, 5, 0, 0}, + {20, 0, 18, 0, 5, 0, 3}, + {21, 0, 18, 0, 4, 0, 12}, + {21, 0, 18, 0, 4, 0, 15}, + {21, 0, 18, 0, 4, 0, 17}, + {27, 0, 17, 0, 5, 0, 30}, + {28, 0, 15, 0, 5, 0, 30}, + {1, 0, 1, 0, 5, 0, 21}, + {1, 0, 5, 0, 5, 0, 21}, + {1, 0, 7, 0, 5, 0, 21}, + {1, 0, 2, 0, 5, 0, 21}, + {1, 0, 6, 0, 5, 0, 21}, + {21, 0, 10, 0, 4, 0, 10}, + {21, 0, 10, 0, 5, 0, 10}, + {21, 0, 18, 0, 4, 0, 10}, + {21, 0, 18, 0, 5, 0, 10}, + {21, 0, 18, 0, 5, 0, 5}, + {16, 0, 18, 0, 5, 0, 12}, + {25, 0, 12, 0, 5, 0, 8}, {22, 0, 18, 1, 5, 0, 0}, - {18, 0, 18, 1, 5, 0, 0}, - {25, 0, 18, 0, 5, 0, 0}, - {1, 0, 19, 0, 5, 0, 0}, - {1, 0, 20, 0, 5, 0, 0}, - {1, 0, 21, 0, 5, 0, 0}, - {1, 0, 22, 0, 5, 0, 0}, - {15, 0, 8, 0, 5, 0, 0}, - {25, 0, 9, 0, 5, 0, 0}, - {6, 0, 0, 0, 4, 0, 1}, - {23, 0, 10, 0, 1, 0, 0}, - {9, 0, 0, 0, 5, 0, 0}, - {5, 0, 0, 0, 4, 0, 0}, - {26, 0, 10, 0, 5, 0, 0}, - {25, 0, 18, 1, 5, 0, 0}, - {15, 0, 18, 0, 5, 0, 0}, - {14, 0, 0, 0, 4, 0, 1}, - {14, 0, 0, 0, 5, 0, 1}, - {25, 0, 18, 1, 4, 0, 0}, - {25, 0, 10, 0, 5, 0, 0}, + {18, 0, 18, 1, 5, 0, 1}, + {25, 0, 18, 0, 5, 0, 12}, + {1, 0, 14, 0, 5, 0, 22}, + {1, 0, 14, 0, 5, 0, 12}, + {1, 0, 19, 0, 5, 0, 21}, + {1, 0, 20, 0, 5, 0, 21}, + {1, 0, 21, 0, 5, 0, 21}, + {1, 0, 22, 0, 5, 0, 21}, + {1, 0, 14, 0, 5, 0, 21}, + {15, 0, 8, 0, 5, 0, 12}, + {25, 0, 9, 0, 5, 0, 12}, + {6, 0, 0, 0, 4, 1, 29}, + {23, 0, 10, 0, 5, 0, 10}, + {23, 0, 10, 0, 1, 0, 9}, + {2, 0, 18, 0, 5, 102, 9}, + {9, 0, 0, 0, 5, 0, 12}, + {26, 0, 18, 0, 4, 0, 10}, + {26, 0, 18, 0, 4, 0, 29}, + {5, 0, 0, 0, 4, 0, 29}, + {26, 0, 18, 0, 4, 0, 9}, + {9, 0, 0, 0, 4, 1, 29}, + {26, 0, 10, 0, 5, 0, 12}, + {25, 0, 18, 1, 5, 0, 12}, + {15, 0, 18, 0, 5, 0, 12}, + {15, 0, 18, 0, 4, 0, 12}, + {15, 0, 18, 0, 5, 0, 29}, + {14, 0, 0, 0, 4, 1, 29}, + {14, 0, 0, 0, 5, 1, 12}, + {25, 0, 18, 1, 4, 0, 29}, + {25, 0, 9, 0, 5, 0, 9}, + {25, 0, 10, 0, 5, 0, 9}, + {25, 0, 18, 0, 5, 0, 15}, + {26, 0, 18, 0, 2, 0, 14}, {22, 0, 18, 1, 2, 0, 0}, - {18, 0, 18, 1, 2, 0, 0}, - {26, 0, 0, 0, 4, 0, 0}, - {26, 0, 0, 0, 5, 0, 52}, - {9, 0, 0, 0, 5, 0, 56}, - {5, 0, 0, 0, 5, 0, 56}, - {26, 0, 18, 0, 5, 0, 54}, - {12, 230, 13, 0, 5, 0, 54}, - {21, 0, 18, 0, 5, 0, 54}, - {15, 0, 18, 0, 5, 0, 54}, - {5, 0, 0, 0, 5, 0, 23}, - {7, 0, 0, 0, 5, 0, 57}, - {6, 0, 0, 0, 5, 0, 57}, - {21, 0, 0, 0, 5, 0, 57}, - {12, 9, 13, 0, 5, 0, 57}, - {26, 0, 18, 0, 2, 0, 35}, - {26, 0, 18, 0, 2, 0, 0}, - {29, 0, 17, 0, 0, 0, 0}, - {21, 0, 18, 0, 2, 0, 0}, - {6, 0, 0, 0, 2, 0, 35}, - {7, 0, 0, 0, 2, 0, 0}, - {14, 0, 0, 0, 2, 0, 35}, - {17, 0, 18, 0, 2, 0, 0}, - {22, 0, 18, 0, 2, 0, 0}, - {18, 0, 18, 0, 2, 0, 0}, - {12, 218, 13, 0, 2, 0, 40}, - {12, 228, 13, 0, 2, 0, 40}, - {12, 232, 13, 0, 2, 0, 40}, - {12, 222, 13, 0, 2, 0, 40}, - {10, 224, 0, 0, 2, 0, 24}, - {6, 0, 0, 0, 2, 0, 0}, - {7, 0, 0, 0, 2, 0, 32}, - {12, 8, 13, 0, 2, 0, 40}, - {24, 0, 18, 0, 2, 0, 0}, - {6, 0, 0, 0, 2, 0, 32}, - {7, 0, 0, 0, 2, 0, 33}, - {6, 0, 0, 0, 2, 0, 33}, - {7, 0, 0, 0, 2, 0, 34}, - {26, 0, 0, 0, 2, 0, 0}, - {15, 0, 0, 0, 2, 0, 0}, - {26, 0, 0, 0, 2, 0, 24}, - {26, 0, 18, 0, 2, 0, 24}, - {15, 0, 0, 0, 4, 0, 0}, - {15, 0, 18, 0, 2, 0, 0}, - {26, 0, 0, 0, 2, 0, 33}, - {7, 0, 0, 0, 2, 0, 35}, - {2, 0, 18, 0, 2, 0, 102}, - {7, 0, 0, 0, 2, 0, 36}, - {6, 0, 0, 0, 2, 0, 36}, - {26, 0, 18, 0, 2, 0, 36}, - {7, 0, 0, 0, 5, 0, 82}, - {6, 0, 0, 0, 5, 0, 82}, - {21, 0, 0, 0, 5, 0, 82}, - {7, 0, 0, 0, 5, 0, 69}, - {6, 0, 0, 0, 5, 0, 69}, - {21, 0, 18, 0, 5, 0, 69}, - {13, 0, 0, 0, 5, 0, 69}, - {7, 0, 0, 0, 5, 0, 3}, + {18, 0, 18, 1, 2, 0, 1}, + {26, 0, 18, 0, 2, 0, 12}, + {26, 0, 18, 0, 5, 0, 14}, + {26, 0, 0, 0, 4, 0, 29}, + {26, 0, 18, 0, 5, 0, 29}, + {25, 0, 18, 0, 2, 0, 12}, + {26, 0, 18, 0, 4, 0, 14}, + {26, 0, 18, 0, 5, 0, 41}, + {26, 0, 18, 0, 4, 0, 41}, + {26, 0, 18, 0, 2, 0, 41}, + {26, 0, 18, 0, 2, 0, 29}, + {26, 0, 18, 0, 5, 0, 3}, + {26, 0, 18, 0, 5, 0, 6}, + {26, 0, 0, 0, 5, 52, 12}, + {9, 0, 0, 0, 5, 56, 12}, + {5, 0, 0, 0, 5, 56, 12}, + {26, 0, 18, 0, 5, 54, 12}, + {12, 230, 13, 0, 5, 54, 21}, + {21, 0, 18, 0, 5, 54, 6}, + {21, 0, 18, 0, 5, 54, 17}, + {15, 0, 18, 0, 5, 54, 12}, + {5, 0, 0, 0, 5, 23, 12}, + {7, 0, 0, 0, 5, 57, 12}, + {6, 0, 0, 0, 5, 57, 12}, + {21, 0, 0, 0, 5, 57, 17}, + {12, 9, 13, 0, 5, 57, 21}, {21, 0, 18, 0, 5, 0, 3}, - {6, 0, 18, 0, 5, 0, 3}, - {7, 0, 0, 0, 5, 0, 83}, - {14, 0, 0, 0, 5, 0, 83}, - {12, 230, 13, 0, 5, 0, 83}, - {21, 0, 0, 0, 5, 0, 83}, - {24, 0, 0, 0, 5, 0, 0}, - {7, 0, 0, 0, 5, 0, 58}, - {12, 0, 13, 0, 5, 0, 58}, - {12, 9, 13, 0, 5, 0, 58}, - {10, 0, 0, 0, 5, 0, 58}, - {26, 0, 18, 0, 5, 0, 58}, - {15, 0, 0, 0, 5, 0, 0}, - {7, 0, 0, 0, 5, 0, 64}, - {21, 0, 18, 0, 5, 0, 64}, - {10, 0, 0, 0, 5, 0, 70}, - {7, 0, 0, 0, 5, 0, 70}, - {12, 9, 13, 0, 5, 0, 70}, - {21, 0, 0, 0, 5, 0, 70}, - {13, 0, 0, 0, 5, 0, 70}, - {13, 0, 0, 0, 5, 0, 71}, - {7, 0, 0, 0, 5, 0, 71}, - {12, 0, 13, 0, 5, 0, 71}, - {12, 220, 13, 0, 5, 0, 71}, - {21, 0, 0, 0, 5, 0, 71}, - {7, 0, 0, 0, 5, 0, 72}, - {12, 0, 13, 0, 5, 0, 72}, - {10, 0, 0, 0, 5, 0, 72}, - {10, 9, 0, 0, 5, 0, 72}, - {21, 0, 0, 0, 5, 0, 72}, - {12, 0, 13, 0, 5, 0, 84}, - {10, 0, 0, 0, 5, 0, 84}, - {7, 0, 0, 0, 5, 0, 84}, - {12, 7, 13, 0, 5, 0, 84}, - {10, 9, 0, 0, 5, 0, 84}, - {21, 0, 0, 0, 5, 0, 84}, - {13, 0, 0, 0, 5, 0, 84}, - {6, 0, 0, 0, 5, 0, 22}, - {7, 0, 0, 0, 5, 0, 76}, - {12, 0, 13, 0, 5, 0, 76}, - {10, 0, 0, 0, 5, 0, 76}, - {13, 0, 0, 0, 5, 0, 76}, - {21, 0, 0, 0, 5, 0, 76}, - {7, 0, 0, 0, 5, 0, 78}, - {12, 230, 13, 0, 5, 0, 78}, - {12, 220, 13, 0, 5, 0, 78}, - {6, 0, 0, 0, 5, 0, 78}, - {21, 0, 0, 0, 5, 0, 78}, - {7, 0, 0, 0, 5, 0, 85}, - {10, 0, 0, 0, 5, 0, 85}, - {12, 0, 13, 0, 5, 0, 85}, - {21, 0, 0, 0, 5, 0, 85}, - {6, 0, 0, 0, 5, 0, 85}, - {12, 9, 13, 0, 5, 0, 85}, - {13, 0, 0, 0, 5, 0, 85}, - {4, 0, 0, 0, 5, 0, 102}, - {3, 0, 0, 0, 4, 0, 102}, - {12, 26, 13, 0, 5, 0, 5}, - {25, 0, 9, 0, 5, 0, 5}, - {24, 0, 4, 0, 5, 0, 6}, - {18, 0, 18, 0, 5, 0, 0}, - {16, 0, 18, 0, 2, 0, 0}, - {21, 0, 12, 0, 2, 0, 0}, - {21, 0, 10, 0, 2, 0, 0}, - {25, 0, 9, 0, 2, 0, 0}, - {17, 0, 9, 0, 2, 0, 0}, - {25, 0, 18, 1, 2, 0, 0}, - {25, 0, 18, 0, 2, 0, 0}, - {23, 0, 10, 0, 2, 0, 0}, - {21, 0, 18, 0, 0, 0, 0}, - {21, 0, 10, 0, 0, 0, 0}, - {23, 0, 10, 0, 0, 0, 0}, + {21, 0, 18, 0, 5, 0, 0}, + {17, 0, 18, 0, 5, 0, 12}, + {17, 0, 18, 0, 5, 0, 19}, + {26, 0, 18, 0, 2, 35, 14}, + {29, 0, 17, 0, 0, 0, 17}, + {21, 0, 18, 0, 2, 0, 1}, + {21, 0, 18, 0, 2, 0, 14}, + {6, 0, 0, 0, 2, 35, 5}, + {7, 0, 0, 0, 2, 0, 14}, + {14, 0, 0, 0, 2, 35, 14}, + {17, 0, 18, 0, 2, 0, 5}, + {22, 0, 18, 0, 2, 0, 0}, + {18, 0, 18, 0, 2, 0, 1}, + {12, 218, 13, 0, 2, 40, 21}, + {12, 228, 13, 0, 2, 40, 21}, + {12, 232, 13, 0, 2, 40, 21}, + {12, 222, 13, 0, 2, 40, 21}, + {10, 224, 0, 0, 2, 24, 21}, + {17, 0, 18, 0, 2, 0, 14}, + {6, 0, 0, 0, 2, 0, 14}, + {6, 0, 0, 0, 2, 0, 21}, + {7, 0, 0, 0, 2, 0, 5}, + {7, 0, 0, 0, 2, 32, 32}, + {7, 0, 0, 0, 2, 32, 14}, + {12, 8, 13, 0, 2, 40, 21}, + {24, 0, 18, 0, 2, 0, 5}, + {6, 0, 0, 0, 2, 32, 5}, + {7, 0, 0, 0, 2, 33, 32}, + {7, 0, 0, 0, 2, 33, 14}, + {21, 0, 18, 0, 2, 0, 5}, + {6, 0, 0, 0, 2, 0, 32}, + {6, 0, 0, 0, 2, 33, 5}, + {7, 0, 0, 0, 2, 34, 14}, + {7, 0, 0, 0, 2, 24, 14}, + {26, 0, 0, 0, 2, 0, 14}, + {15, 0, 0, 0, 2, 0, 14}, + {26, 0, 0, 0, 2, 24, 14}, + {26, 0, 18, 0, 2, 24, 14}, + {15, 0, 0, 0, 4, 0, 29}, + {15, 0, 18, 0, 2, 0, 14}, + {26, 0, 0, 0, 2, 33, 14}, + {7, 0, 0, 0, 2, 35, 14}, + {2, 0, 18, 0, 2, 102, 14}, + {7, 0, 0, 0, 2, 36, 14}, + {6, 0, 0, 0, 2, 36, 5}, + {26, 0, 18, 0, 2, 36, 14}, + {7, 0, 0, 0, 5, 82, 12}, + {6, 0, 0, 0, 5, 82, 12}, + {21, 0, 0, 0, 5, 82, 17}, + {7, 0, 0, 0, 5, 69, 12}, + {6, 0, 0, 0, 5, 69, 12}, + {21, 0, 18, 0, 5, 69, 17}, + {21, 0, 18, 0, 5, 69, 6}, + {13, 0, 0, 0, 5, 69, 11}, + {7, 0, 0, 0, 5, 3, 12}, + {21, 0, 18, 0, 5, 3, 12}, + {6, 0, 18, 0, 5, 3, 12}, + {7, 0, 0, 0, 5, 83, 12}, + {14, 0, 0, 0, 5, 83, 12}, + {12, 230, 13, 0, 5, 83, 21}, + {21, 0, 0, 0, 5, 83, 12}, + {21, 0, 0, 0, 5, 83, 17}, + {24, 0, 0, 0, 5, 0, 12}, + {7, 0, 0, 0, 5, 58, 12}, + {12, 0, 13, 0, 5, 58, 21}, + {12, 9, 13, 0, 5, 58, 21}, + {10, 0, 0, 0, 5, 58, 21}, + {26, 0, 18, 0, 5, 58, 12}, + {15, 0, 0, 0, 5, 0, 12}, + {7, 0, 0, 0, 5, 64, 12}, + {21, 0, 18, 0, 5, 64, 18}, + {21, 0, 18, 0, 5, 64, 6}, + {10, 0, 0, 0, 5, 70, 21}, + {7, 0, 0, 0, 5, 70, 12}, + {12, 9, 13, 0, 5, 70, 21}, + {12, 0, 13, 0, 5, 70, 21}, + {21, 0, 0, 0, 5, 70, 17}, + {13, 0, 0, 0, 5, 70, 11}, + {21, 0, 0, 0, 5, 9, 18}, + {13, 0, 0, 0, 5, 71, 11}, + {7, 0, 0, 0, 5, 71, 12}, + {12, 0, 13, 0, 5, 71, 21}, + {12, 220, 13, 0, 5, 71, 21}, + {21, 0, 0, 0, 5, 71, 17}, + {7, 0, 0, 0, 5, 72, 12}, + {12, 0, 13, 0, 5, 72, 21}, + {10, 0, 0, 0, 5, 72, 21}, + {10, 9, 0, 0, 5, 72, 21}, + {21, 0, 0, 0, 5, 72, 12}, + {12, 0, 13, 0, 5, 84, 21}, + {10, 0, 0, 0, 5, 84, 21}, + {7, 0, 0, 0, 5, 84, 12}, + {12, 7, 13, 0, 5, 84, 21}, + {10, 9, 0, 0, 5, 84, 21}, + {21, 0, 0, 0, 5, 84, 12}, + {21, 0, 0, 0, 5, 84, 17}, + {13, 0, 0, 0, 5, 84, 11}, + {6, 0, 0, 0, 5, 22, 38}, + {7, 0, 0, 0, 5, 76, 12}, + {12, 0, 13, 0, 5, 76, 21}, + {10, 0, 0, 0, 5, 76, 21}, + {13, 0, 0, 0, 5, 76, 11}, + {21, 0, 0, 0, 5, 76, 12}, + {21, 0, 0, 0, 5, 76, 17}, + {7, 0, 0, 0, 5, 78, 38}, + {12, 230, 13, 0, 5, 78, 38}, + {12, 220, 13, 0, 5, 78, 38}, + {6, 0, 0, 0, 5, 78, 38}, + {21, 0, 0, 0, 5, 78, 38}, + {7, 0, 0, 0, 5, 85, 12}, + {10, 0, 0, 0, 5, 85, 21}, + {12, 0, 13, 0, 5, 85, 21}, + {21, 0, 0, 0, 5, 85, 17}, + {6, 0, 0, 0, 5, 85, 12}, + {12, 9, 13, 0, 5, 85, 21}, + {13, 0, 0, 0, 5, 85, 11}, + {7, 0, 0, 0, 2, 24, 23}, + {7, 0, 0, 0, 2, 24, 24}, + {4, 0, 0, 0, 5, 102, 39}, + {3, 0, 0, 0, 4, 102, 41}, + {12, 26, 13, 0, 5, 5, 21}, + {25, 0, 9, 0, 5, 5, 12}, + {24, 0, 4, 0, 5, 6, 12}, + {18, 0, 18, 0, 5, 0, 1}, + {12, 0, 13, 0, 4, 40, 21}, + {21, 0, 18, 0, 2, 0, 8}, + {21, 0, 18, 0, 2, 0, 6}, + {21, 0, 18, 0, 2, 0, 15}, + {16, 0, 18, 0, 2, 0, 14}, + {21, 0, 12, 0, 2, 0, 1}, + {21, 0, 12, 0, 2, 0, 5}, + {21, 0, 10, 0, 2, 0, 14}, + {25, 0, 9, 0, 2, 0, 14}, + {17, 0, 9, 0, 2, 0, 14}, + {25, 0, 18, 1, 2, 0, 14}, + {25, 0, 18, 0, 2, 0, 14}, + {23, 0, 10, 0, 2, 0, 9}, + {21, 0, 10, 0, 2, 0, 10}, + {21, 0, 18, 0, 0, 0, 6}, + {21, 0, 18, 0, 0, 0, 14}, + {21, 0, 10, 0, 0, 0, 14}, + {23, 0, 10, 0, 0, 0, 9}, + {21, 0, 10, 0, 0, 0, 10}, {22, 0, 18, 1, 0, 0, 0}, - {18, 0, 18, 1, 0, 0, 0}, - {25, 0, 9, 0, 0, 0, 0}, - {21, 0, 12, 0, 0, 0, 0}, - {17, 0, 9, 0, 0, 0, 0}, - {13, 0, 8, 0, 0, 0, 0}, - {25, 0, 18, 1, 0, 0, 0}, - {25, 0, 18, 0, 0, 0, 0}, - {9, 0, 0, 0, 0, 0, 1}, - {24, 0, 18, 0, 0, 0, 0}, - {16, 0, 18, 0, 0, 0, 0}, - {5, 0, 0, 0, 0, 0, 1}, - {21, 0, 18, 0, 1, 0, 0}, + {18, 0, 18, 1, 0, 0, 1}, + {25, 0, 9, 0, 0, 0, 14}, + {21, 0, 12, 0, 0, 0, 1}, + {17, 0, 9, 0, 0, 0, 14}, + {21, 0, 12, 0, 0, 0, 14}, + {13, 0, 8, 0, 0, 0, 14}, + {21, 0, 12, 0, 0, 0, 5}, + {21, 0, 18, 0, 0, 0, 5}, + {25, 0, 18, 1, 0, 0, 14}, + {25, 0, 18, 0, 0, 0, 14}, + {9, 0, 0, 0, 0, 1, 14}, + {24, 0, 18, 0, 0, 0, 14}, + {16, 0, 18, 0, 0, 0, 14}, + {5, 0, 0, 0, 0, 1, 14}, + {21, 0, 18, 0, 1, 0, 1}, {22, 0, 18, 1, 1, 0, 0}, - {18, 0, 18, 1, 1, 0, 0}, - {7, 0, 0, 0, 1, 0, 33}, - {6, 0, 0, 0, 1, 0, 0}, - {7, 0, 0, 0, 1, 0, 24}, - {26, 0, 18, 0, 0, 0, 0}, - {26, 0, 18, 0, 1, 0, 0}, - {25, 0, 18, 0, 1, 0, 0}, - {1, 0, 18, 0, 5, 0, 0}, - {7, 0, 0, 0, 5, 0, 47}, - {14, 0, 18, 0, 5, 0, 2}, - {15, 0, 18, 0, 5, 0, 2}, - {26, 0, 18, 0, 5, 0, 2}, - {7, 0, 0, 0, 5, 0, 73}, - {7, 0, 0, 0, 5, 0, 74}, - {7, 0, 0, 0, 5, 0, 37}, - {15, 0, 0, 0, 5, 0, 37}, - {7, 0, 0, 0, 5, 0, 38}, - {14, 0, 0, 0, 5, 0, 38}, - {7, 0, 0, 0, 5, 0, 118}, - {12, 230, 13, 0, 5, 0, 118}, - {7, 0, 0, 0, 5, 0, 48}, - {21, 0, 0, 0, 5, 0, 48}, - {7, 0, 0, 0, 5, 0, 59}, - {21, 0, 0, 0, 5, 0, 59}, - {14, 0, 0, 0, 5, 0, 59}, - {9, 0, 0, 0, 5, 0, 39}, - {5, 0, 0, 0, 5, 0, 39}, - {7, 0, 0, 0, 5, 0, 49}, - {7, 0, 0, 0, 5, 0, 50}, - {13, 0, 0, 0, 5, 0, 50}, - {7, 0, 0, 0, 5, 0, 106}, - {7, 0, 0, 0, 5, 0, 104}, - {21, 0, 0, 0, 5, 0, 104}, - {7, 0, 0, 0, 5, 0, 110}, - {7, 0, 3, 0, 5, 0, 51}, - {7, 0, 3, 0, 5, 0, 86}, - {21, 0, 3, 0, 5, 0, 86}, - {15, 0, 3, 0, 5, 0, 86}, - {7, 0, 3, 0, 5, 0, 120}, - {26, 0, 3, 0, 5, 0, 120}, - {15, 0, 3, 0, 5, 0, 120}, - {7, 0, 3, 0, 5, 0, 116}, - {15, 0, 3, 0, 5, 0, 116}, - {7, 0, 3, 0, 5, 0, 128}, - {15, 0, 3, 0, 5, 0, 128}, - {7, 0, 3, 0, 5, 0, 63}, - {15, 0, 3, 0, 5, 0, 63}, - {21, 0, 18, 0, 5, 0, 63}, - {7, 0, 3, 0, 5, 0, 75}, - {21, 0, 3, 0, 5, 0, 75}, - {7, 0, 3, 0, 5, 0, 97}, - {7, 0, 3, 0, 5, 0, 96}, - {15, 0, 3, 0, 5, 0, 96}, - {7, 0, 3, 0, 5, 0, 60}, - {12, 0, 13, 0, 5, 0, 60}, - {12, 220, 13, 0, 5, 0, 60}, - {12, 230, 13, 0, 5, 0, 60}, - {12, 1, 13, 0, 5, 0, 60}, - {12, 9, 13, 0, 5, 0, 60}, - {15, 0, 3, 0, 5, 0, 60}, - {21, 0, 3, 0, 5, 0, 60}, - {7, 0, 3, 0, 5, 0, 87}, - {15, 0, 3, 0, 5, 0, 87}, - {21, 0, 3, 0, 5, 0, 87}, - {7, 0, 3, 0, 5, 0, 117}, - {15, 0, 3, 0, 5, 0, 117}, - {7, 0, 3, 0, 5, 0, 112}, - {26, 0, 3, 0, 5, 0, 112}, - {12, 230, 13, 0, 5, 0, 112}, - {12, 220, 13, 0, 5, 0, 112}, - {15, 0, 3, 0, 5, 0, 112}, - {21, 0, 3, 0, 5, 0, 112}, - {7, 0, 3, 0, 5, 0, 79}, - {21, 0, 18, 0, 5, 0, 79}, - {7, 0, 3, 0, 5, 0, 88}, - {15, 0, 3, 0, 5, 0, 88}, - {7, 0, 3, 0, 5, 0, 89}, - {15, 0, 3, 0, 5, 0, 89}, - {7, 0, 3, 0, 5, 0, 122}, - {21, 0, 3, 0, 5, 0, 122}, - {15, 0, 3, 0, 5, 0, 122}, - {7, 0, 3, 0, 5, 0, 90}, - {9, 0, 3, 0, 5, 0, 130}, - {5, 0, 3, 0, 5, 0, 130}, - {15, 0, 3, 0, 5, 0, 130}, - {15, 0, 11, 0, 5, 0, 6}, - {10, 0, 0, 0, 5, 0, 93}, - {12, 0, 13, 0, 5, 0, 93}, - {7, 0, 0, 0, 5, 0, 93}, - {12, 9, 13, 0, 5, 0, 93}, - {21, 0, 0, 0, 5, 0, 93}, - {15, 0, 18, 0, 5, 0, 93}, - {13, 0, 0, 0, 5, 0, 93}, - {12, 0, 13, 0, 5, 0, 91}, - {10, 0, 0, 0, 5, 0, 91}, - {7, 0, 0, 0, 5, 0, 91}, - {12, 9, 13, 0, 5, 0, 91}, - {12, 7, 13, 0, 5, 0, 91}, - {21, 0, 0, 0, 5, 0, 91}, - {1, 0, 0, 0, 5, 0, 91}, - {7, 0, 0, 0, 5, 0, 100}, - {13, 0, 0, 0, 5, 0, 100}, - {12, 230, 13, 0, 5, 0, 95}, - {7, 0, 0, 0, 5, 0, 95}, - {12, 0, 13, 0, 5, 0, 95}, - {10, 0, 0, 0, 5, 0, 95}, - {12, 9, 13, 0, 5, 0, 95}, - {13, 0, 0, 0, 5, 0, 95}, - {21, 0, 0, 0, 5, 0, 95}, - {7, 0, 0, 0, 5, 0, 111}, - {12, 7, 13, 0, 5, 0, 111}, - {21, 0, 0, 0, 5, 0, 111}, - {12, 0, 13, 0, 5, 0, 99}, - {10, 0, 0, 0, 5, 0, 99}, - {7, 0, 0, 0, 5, 0, 99}, - {10, 9, 0, 0, 5, 0, 99}, - {21, 0, 0, 0, 5, 0, 99}, - {12, 7, 13, 0, 5, 0, 99}, - {13, 0, 0, 0, 5, 0, 99}, - {15, 0, 0, 0, 5, 0, 18}, - {7, 0, 0, 0, 5, 0, 108}, - {10, 0, 0, 0, 5, 0, 108}, - {12, 0, 13, 0, 5, 0, 108}, - {10, 9, 0, 0, 5, 0, 108}, - {12, 7, 13, 0, 5, 0, 108}, - {21, 0, 0, 0, 5, 0, 108}, - {7, 0, 0, 0, 5, 0, 129}, - {21, 0, 0, 0, 5, 0, 129}, - {7, 0, 0, 0, 5, 0, 109}, - {12, 0, 13, 0, 5, 0, 109}, - {10, 0, 0, 0, 5, 0, 109}, - {12, 7, 13, 0, 5, 0, 109}, - {12, 9, 13, 0, 5, 0, 109}, - {13, 0, 0, 0, 5, 0, 109}, - {12, 0, 13, 0, 5, 0, 107}, - {10, 0, 0, 0, 5, 0, 107}, - {7, 0, 0, 0, 5, 0, 107}, - {12, 7, 13, 0, 5, 0, 107}, - {10, 9, 0, 0, 5, 0, 107}, - {12, 230, 13, 0, 5, 0, 107}, - {7, 0, 0, 0, 5, 0, 124}, - {10, 0, 0, 0, 5, 0, 124}, - {12, 0, 13, 0, 5, 0, 124}, - {12, 9, 13, 0, 5, 0, 124}, - {12, 7, 13, 0, 5, 0, 124}, - {21, 0, 0, 0, 5, 0, 124}, - {13, 0, 0, 0, 5, 0, 124}, - {7, 0, 0, 0, 5, 0, 123}, - {10, 0, 0, 0, 5, 0, 123}, - {12, 0, 13, 0, 5, 0, 123}, - {12, 9, 13, 0, 5, 0, 123}, - {12, 7, 13, 0, 5, 0, 123}, - {21, 0, 0, 0, 5, 0, 123}, - {7, 0, 0, 0, 5, 0, 114}, - {10, 0, 0, 0, 5, 0, 114}, - {12, 0, 13, 0, 5, 0, 114}, - {12, 9, 13, 0, 5, 0, 114}, - {21, 0, 0, 0, 5, 0, 114}, - {13, 0, 0, 0, 5, 0, 114}, - {7, 0, 0, 0, 5, 0, 101}, - {12, 0, 13, 0, 5, 0, 101}, - {10, 0, 0, 0, 5, 0, 101}, - {10, 9, 0, 0, 5, 0, 101}, - {12, 7, 13, 0, 5, 0, 101}, - {13, 0, 0, 0, 5, 0, 101}, - {7, 0, 0, 0, 5, 0, 126}, - {12, 0, 13, 0, 5, 0, 126}, - {10, 0, 0, 0, 5, 0, 126}, - {12, 9, 13, 0, 5, 0, 126}, - {13, 0, 0, 0, 5, 0, 126}, - {15, 0, 0, 0, 5, 0, 126}, - {21, 0, 0, 0, 5, 0, 126}, - {26, 0, 0, 0, 5, 0, 126}, - {9, 0, 0, 0, 5, 0, 125}, - {5, 0, 0, 0, 5, 0, 125}, - {13, 0, 0, 0, 5, 0, 125}, - {15, 0, 0, 0, 5, 0, 125}, - {7, 0, 0, 0, 5, 0, 125}, - {7, 0, 0, 0, 5, 0, 121}, - {7, 0, 0, 0, 5, 0, 62}, - {14, 0, 0, 0, 5, 0, 62}, - {21, 0, 0, 0, 5, 0, 62}, - {7, 0, 0, 0, 5, 0, 80}, - {7, 0, 0, 0, 5, 0, 127}, - {7, 0, 0, 0, 5, 0, 115}, - {13, 0, 0, 0, 5, 0, 115}, - {21, 0, 0, 0, 5, 0, 115}, - {7, 0, 0, 0, 5, 0, 103}, - {12, 1, 13, 0, 5, 0, 103}, - {21, 0, 0, 0, 5, 0, 103}, - {7, 0, 0, 0, 5, 0, 119}, - {12, 230, 13, 0, 5, 0, 119}, - {21, 0, 0, 0, 5, 0, 119}, - {26, 0, 0, 0, 5, 0, 119}, - {6, 0, 0, 0, 5, 0, 119}, - {13, 0, 0, 0, 5, 0, 119}, - {15, 0, 0, 0, 5, 0, 119}, - {7, 0, 0, 0, 5, 0, 98}, - {10, 0, 0, 0, 5, 0, 98}, - {12, 0, 13, 0, 5, 0, 98}, - {6, 0, 0, 0, 5, 0, 98}, - {7, 0, 0, 0, 5, 0, 105}, - {26, 0, 0, 0, 5, 0, 105}, - {12, 0, 13, 0, 5, 0, 105}, - {12, 1, 13, 0, 5, 0, 105}, - {21, 0, 0, 0, 5, 0, 105}, - {10, 216, 0, 0, 5, 0, 0}, - {10, 226, 0, 0, 5, 0, 0}, - {12, 230, 13, 0, 5, 0, 2}, - {25, 0, 0, 0, 5, 0, 0}, - {13, 0, 8, 0, 5, 0, 0}, - {26, 0, 0, 0, 5, 0, 131}, - {12, 0, 13, 0, 5, 0, 131}, - {21, 0, 0, 0, 5, 0, 131}, - {7, 0, 3, 0, 5, 0, 113}, - {15, 0, 3, 0, 5, 0, 113}, - {12, 220, 13, 0, 5, 0, 113}, - {26, 0, 0, 0, 2, 0, 32}, + {18, 0, 18, 1, 1, 0, 1}, + {21, 0, 18, 0, 1, 0, 5}, + {7, 0, 0, 0, 1, 33, 14}, + {7, 0, 0, 0, 1, 33, 32}, + {6, 0, 0, 0, 1, 0, 32}, + {6, 0, 0, 0, 1, 0, 5}, + {7, 0, 0, 0, 1, 24, 14}, + {23, 0, 10, 0, 0, 0, 10}, + {26, 0, 18, 0, 0, 0, 14}, + {26, 0, 18, 0, 1, 0, 12}, + {25, 0, 18, 0, 1, 0, 12}, + {1, 0, 18, 0, 5, 0, 21}, + {26, 0, 18, 0, 5, 0, 31}, + {7, 0, 0, 0, 5, 47, 12}, + {14, 0, 18, 0, 5, 2, 12}, + {15, 0, 18, 0, 5, 2, 12}, + {26, 0, 18, 0, 5, 2, 12}, + {26, 0, 0, 0, 5, 2, 12}, + {7, 0, 0, 0, 5, 73, 12}, + {7, 0, 0, 0, 5, 74, 12}, + {7, 0, 0, 0, 5, 37, 12}, + {15, 0, 0, 0, 5, 37, 12}, + {7, 0, 0, 0, 5, 38, 12}, + {14, 0, 0, 0, 5, 38, 12}, + {7, 0, 0, 0, 5, 118, 12}, + {12, 230, 13, 0, 5, 118, 21}, + {7, 0, 0, 0, 5, 48, 12}, + {21, 0, 0, 0, 5, 48, 17}, + {7, 0, 0, 0, 5, 59, 12}, + {21, 0, 0, 0, 5, 59, 17}, + {14, 0, 0, 0, 5, 59, 12}, + {9, 0, 0, 0, 5, 39, 12}, + {5, 0, 0, 0, 5, 39, 12}, + {7, 0, 0, 0, 5, 49, 12}, + {7, 0, 0, 0, 5, 50, 12}, + {13, 0, 0, 0, 5, 50, 11}, + {9, 0, 0, 0, 5, 136, 12}, + {5, 0, 0, 0, 5, 136, 12}, + {7, 0, 0, 0, 5, 106, 12}, + {7, 0, 0, 0, 5, 104, 12}, + {21, 0, 0, 0, 5, 104, 12}, + {7, 0, 0, 0, 5, 110, 12}, + {7, 0, 3, 0, 5, 51, 12}, + {7, 0, 3, 0, 5, 86, 12}, + {21, 0, 3, 0, 5, 86, 17}, + {15, 0, 3, 0, 5, 86, 12}, + {7, 0, 3, 0, 5, 120, 12}, + {26, 0, 3, 0, 5, 120, 12}, + {15, 0, 3, 0, 5, 120, 12}, + {7, 0, 3, 0, 5, 116, 12}, + {15, 0, 3, 0, 5, 116, 12}, + {7, 0, 3, 0, 5, 128, 12}, + {15, 0, 3, 0, 5, 128, 12}, + {7, 0, 3, 0, 5, 63, 12}, + {15, 0, 3, 0, 5, 63, 12}, + {21, 0, 18, 0, 5, 63, 17}, + {7, 0, 3, 0, 5, 75, 12}, + {21, 0, 3, 0, 5, 75, 12}, + {7, 0, 3, 0, 5, 97, 12}, + {7, 0, 3, 0, 5, 96, 12}, + {15, 0, 3, 0, 5, 96, 12}, + {7, 0, 3, 0, 5, 60, 12}, + {12, 0, 13, 0, 5, 60, 21}, + {12, 220, 13, 0, 5, 60, 21}, + {12, 230, 13, 0, 5, 60, 21}, + {12, 1, 13, 0, 5, 60, 21}, + {12, 9, 13, 0, 5, 60, 21}, + {15, 0, 3, 0, 5, 60, 12}, + {21, 0, 3, 0, 5, 60, 17}, + {21, 0, 3, 0, 5, 60, 12}, + {7, 0, 3, 0, 5, 87, 12}, + {15, 0, 3, 0, 5, 87, 12}, + {21, 0, 3, 0, 5, 87, 12}, + {7, 0, 3, 0, 5, 117, 12}, + {15, 0, 3, 0, 5, 117, 12}, + {7, 0, 3, 0, 5, 112, 12}, + {26, 0, 3, 0, 5, 112, 12}, + {12, 230, 13, 0, 5, 112, 21}, + {12, 220, 13, 0, 5, 112, 21}, + {15, 0, 3, 0, 5, 112, 12}, + {21, 0, 3, 0, 5, 112, 17}, + {21, 0, 3, 0, 5, 112, 15}, + {7, 0, 3, 0, 5, 79, 12}, + {21, 0, 18, 0, 5, 79, 17}, + {7, 0, 3, 0, 5, 88, 12}, + {15, 0, 3, 0, 5, 88, 12}, + {7, 0, 3, 0, 5, 89, 12}, + {15, 0, 3, 0, 5, 89, 12}, + {7, 0, 3, 0, 5, 122, 12}, + {21, 0, 3, 0, 5, 122, 12}, + {15, 0, 3, 0, 5, 122, 12}, + {7, 0, 3, 0, 5, 90, 12}, + {9, 0, 3, 0, 5, 130, 12}, + {5, 0, 3, 0, 5, 130, 12}, + {15, 0, 3, 0, 5, 130, 12}, + {15, 0, 11, 0, 5, 6, 12}, + {10, 0, 0, 0, 5, 93, 21}, + {12, 0, 13, 0, 5, 93, 21}, + {7, 0, 0, 0, 5, 93, 12}, + {12, 9, 13, 0, 5, 93, 21}, + {21, 0, 0, 0, 5, 93, 17}, + {21, 0, 0, 0, 5, 93, 12}, + {15, 0, 18, 0, 5, 93, 12}, + {13, 0, 0, 0, 5, 93, 11}, + {12, 0, 13, 0, 5, 91, 21}, + {10, 0, 0, 0, 5, 91, 21}, + {7, 0, 0, 0, 5, 91, 12}, + {12, 9, 13, 0, 5, 91, 21}, + {12, 7, 13, 0, 5, 91, 21}, + {21, 0, 0, 0, 5, 91, 12}, + {1, 0, 0, 0, 5, 91, 12}, + {21, 0, 0, 0, 5, 91, 17}, + {7, 0, 0, 0, 5, 100, 12}, + {13, 0, 0, 0, 5, 100, 11}, + {12, 230, 13, 0, 5, 95, 21}, + {7, 0, 0, 0, 5, 95, 12}, + {12, 0, 13, 0, 5, 95, 21}, + {10, 0, 0, 0, 5, 95, 21}, + {12, 9, 13, 0, 5, 95, 21}, + {13, 0, 0, 0, 5, 95, 11}, + {21, 0, 0, 0, 5, 95, 17}, + {7, 0, 0, 0, 5, 111, 12}, + {12, 7, 13, 0, 5, 111, 21}, + {21, 0, 0, 0, 5, 111, 12}, + {21, 0, 0, 0, 5, 111, 18}, + {12, 0, 13, 0, 5, 99, 21}, + {10, 0, 0, 0, 5, 99, 21}, + {7, 0, 0, 0, 5, 99, 12}, + {10, 9, 0, 0, 5, 99, 21}, + {21, 0, 0, 0, 5, 99, 17}, + {21, 0, 0, 0, 5, 99, 12}, + {12, 7, 13, 0, 5, 99, 21}, + {13, 0, 0, 0, 5, 99, 11}, + {21, 0, 0, 0, 5, 99, 18}, + {15, 0, 0, 0, 5, 18, 12}, + {7, 0, 0, 0, 5, 108, 12}, + {10, 0, 0, 0, 5, 108, 21}, + {12, 0, 13, 0, 5, 108, 21}, + {10, 9, 0, 0, 5, 108, 21}, + {12, 7, 13, 0, 5, 108, 21}, + {21, 0, 0, 0, 5, 108, 17}, + {21, 0, 0, 0, 5, 108, 12}, + {7, 0, 0, 0, 5, 129, 12}, + {21, 0, 0, 0, 5, 129, 17}, + {7, 0, 0, 0, 5, 109, 12}, + {12, 0, 13, 0, 5, 109, 21}, + {10, 0, 0, 0, 5, 109, 21}, + {12, 7, 13, 0, 5, 109, 21}, + {12, 9, 13, 0, 5, 109, 21}, + {13, 0, 0, 0, 5, 109, 11}, + {12, 0, 13, 0, 5, 107, 21}, + {10, 0, 0, 0, 5, 107, 21}, + {7, 0, 0, 0, 5, 107, 12}, + {12, 7, 13, 0, 5, 107, 21}, + {10, 9, 0, 0, 5, 107, 21}, + {12, 230, 13, 0, 5, 107, 21}, + {7, 0, 0, 0, 5, 135, 12}, + {10, 0, 0, 0, 5, 135, 21}, + {12, 0, 13, 0, 5, 135, 21}, + {12, 9, 13, 0, 5, 135, 21}, + {12, 7, 13, 0, 5, 135, 21}, + {21, 0, 0, 0, 5, 135, 17}, + {21, 0, 0, 0, 5, 135, 12}, + {13, 0, 0, 0, 5, 135, 11}, + {7, 0, 0, 0, 5, 124, 12}, + {10, 0, 0, 0, 5, 124, 21}, + {12, 0, 13, 0, 5, 124, 21}, + {12, 9, 13, 0, 5, 124, 21}, + {12, 7, 13, 0, 5, 124, 21}, + {21, 0, 0, 0, 5, 124, 12}, + {13, 0, 0, 0, 5, 124, 11}, + {7, 0, 0, 0, 5, 123, 12}, + {10, 0, 0, 0, 5, 123, 21}, + {12, 0, 13, 0, 5, 123, 21}, + {12, 9, 13, 0, 5, 123, 21}, + {12, 7, 13, 0, 5, 123, 21}, + {21, 0, 0, 0, 5, 123, 18}, + {21, 0, 0, 0, 5, 123, 17}, + {21, 0, 0, 0, 5, 123, 6}, + {21, 0, 0, 0, 5, 123, 12}, + {7, 0, 0, 0, 5, 114, 12}, + {10, 0, 0, 0, 5, 114, 21}, + {12, 0, 13, 0, 5, 114, 21}, + {12, 9, 13, 0, 5, 114, 21}, + {21, 0, 0, 0, 5, 114, 17}, + {21, 0, 0, 0, 5, 114, 12}, + {13, 0, 0, 0, 5, 114, 11}, + {21, 0, 18, 0, 5, 31, 18}, + {7, 0, 0, 0, 5, 101, 12}, + {12, 0, 13, 0, 5, 101, 21}, + {10, 0, 0, 0, 5, 101, 21}, + {10, 9, 0, 0, 5, 101, 21}, + {12, 7, 13, 0, 5, 101, 21}, + {13, 0, 0, 0, 5, 101, 11}, + {7, 0, 0, 0, 5, 126, 38}, + {12, 0, 13, 0, 5, 126, 38}, + {10, 0, 0, 0, 5, 126, 38}, + {12, 9, 13, 0, 5, 126, 38}, + {13, 0, 0, 0, 5, 126, 11}, + {15, 0, 0, 0, 5, 126, 38}, + {21, 0, 0, 0, 5, 126, 17}, + {26, 0, 0, 0, 5, 126, 38}, + {9, 0, 0, 0, 5, 125, 12}, + {5, 0, 0, 0, 5, 125, 12}, + {13, 0, 0, 0, 5, 125, 11}, + {15, 0, 0, 0, 5, 125, 12}, + {7, 0, 0, 0, 5, 125, 12}, + {7, 0, 0, 0, 5, 121, 12}, + {7, 0, 0, 0, 5, 133, 12}, + {10, 0, 0, 0, 5, 133, 21}, + {12, 0, 13, 0, 5, 133, 21}, + {12, 9, 0, 0, 5, 133, 21}, + {21, 0, 0, 0, 5, 133, 17}, + {13, 0, 0, 0, 5, 133, 11}, + {15, 0, 0, 0, 5, 133, 12}, + {21, 0, 0, 0, 5, 134, 18}, + {21, 0, 0, 0, 5, 134, 6}, + {7, 0, 0, 0, 5, 134, 12}, + {12, 0, 13, 0, 5, 134, 21}, + {10, 0, 0, 0, 5, 134, 21}, + {7, 0, 0, 0, 5, 62, 12}, + {14, 0, 0, 0, 5, 62, 12}, + {21, 0, 0, 0, 5, 62, 17}, + {7, 0, 0, 0, 5, 80, 12}, + {7, 0, 0, 0, 5, 80, 0}, + {7, 0, 0, 0, 5, 80, 1}, + {7, 0, 0, 0, 5, 127, 12}, + {7, 0, 0, 0, 5, 127, 0}, + {7, 0, 0, 0, 5, 127, 1}, + {7, 0, 0, 0, 5, 115, 12}, + {13, 0, 0, 0, 5, 115, 11}, + {21, 0, 0, 0, 5, 115, 17}, + {7, 0, 0, 0, 5, 103, 12}, + {12, 1, 13, 0, 5, 103, 21}, + {21, 0, 0, 0, 5, 103, 17}, + {7, 0, 0, 0, 5, 119, 12}, + {12, 230, 13, 0, 5, 119, 21}, + {21, 0, 0, 0, 5, 119, 17}, + {21, 0, 0, 0, 5, 119, 12}, + {26, 0, 0, 0, 5, 119, 12}, + {6, 0, 0, 0, 5, 119, 12}, + {13, 0, 0, 0, 5, 119, 11}, + {15, 0, 0, 0, 5, 119, 12}, + {7, 0, 0, 0, 5, 98, 12}, + {10, 0, 0, 0, 5, 98, 21}, + {12, 0, 13, 0, 5, 98, 21}, + {6, 0, 0, 0, 5, 98, 12}, + {6, 0, 0, 0, 2, 137, 5}, + {7, 0, 0, 0, 2, 137, 14}, + {7, 0, 0, 0, 5, 105, 12}, + {26, 0, 0, 0, 5, 105, 12}, + {12, 0, 13, 0, 5, 105, 21}, + {12, 1, 13, 0, 5, 105, 21}, + {21, 0, 0, 0, 5, 105, 17}, + {10, 216, 0, 0, 5, 0, 21}, + {10, 226, 0, 0, 5, 0, 21}, + {12, 230, 13, 0, 5, 2, 21}, + {25, 0, 0, 0, 5, 0, 12}, + {13, 0, 8, 0, 5, 0, 11}, + {26, 0, 0, 0, 5, 131, 12}, + {12, 0, 13, 0, 5, 131, 21}, + {21, 0, 0, 0, 5, 131, 17}, + {21, 0, 0, 0, 5, 131, 12}, + {12, 230, 13, 0, 5, 56, 21}, + {7, 0, 3, 0, 5, 113, 12}, + {15, 0, 3, 0, 5, 113, 12}, + {12, 220, 13, 0, 5, 113, 21}, + {9, 0, 3, 0, 5, 132, 12}, + {5, 0, 3, 0, 5, 132, 12}, + {12, 230, 13, 0, 5, 132, 21}, + {12, 7, 13, 0, 5, 132, 21}, + {13, 0, 3, 0, 5, 132, 11}, + {21, 0, 3, 0, 5, 132, 0}, + {2, 0, 18, 0, 5, 102, 14}, + {26, 0, 0, 0, 2, 0, 29}, + {26, 0, 0, 0, 5, 0, 28}, + {26, 0, 0, 0, 2, 32, 14}, + {24, 0, 18, 0, 2, 0, 41}, + {26, 0, 18, 0, 5, 0, 5}, }; #define BIDI_MIRROR_LEN 364 @@ -1186,6 +1364,130 @@ static const MirrorPair mirror_pairs[] = { {65379, 65378}, }; +#define BIDI_BRACKET_LEN 120 +static const BracketPair bracket_pairs[] = { + {40, 41, 0}, + {41, 40, 1}, + {91, 93, 0}, + {93, 91, 1}, + {123, 125, 0}, + {125, 123, 1}, + {3898, 3899, 0}, + {3899, 3898, 1}, + {3900, 3901, 0}, + {3901, 3900, 1}, + {5787, 5788, 0}, + {5788, 5787, 1}, + {8261, 8262, 0}, + {8262, 8261, 1}, + {8317, 8318, 0}, + {8318, 8317, 1}, + {8333, 8334, 0}, + {8334, 8333, 1}, + {8968, 8969, 0}, + {8969, 8968, 1}, + {8970, 8971, 0}, + {8971, 8970, 1}, + {9001, 9002, 0}, + {9002, 9001, 1}, + {10088, 10089, 0}, + {10089, 10088, 1}, + {10090, 10091, 0}, + {10091, 10090, 1}, + {10092, 10093, 0}, + {10093, 10092, 1}, + {10094, 10095, 0}, + {10095, 10094, 1}, + {10096, 10097, 0}, + {10097, 10096, 1}, + {10098, 10099, 0}, + {10099, 10098, 1}, + {10100, 10101, 0}, + {10101, 10100, 1}, + {10181, 10182, 0}, + {10182, 10181, 1}, + {10214, 10215, 0}, + {10215, 10214, 1}, + {10216, 10217, 0}, + {10217, 10216, 1}, + {10218, 10219, 0}, + {10219, 10218, 1}, + {10220, 10221, 0}, + {10221, 10220, 1}, + {10222, 10223, 0}, + {10223, 10222, 1}, + {10627, 10628, 0}, + {10628, 10627, 1}, + {10629, 10630, 0}, + {10630, 10629, 1}, + {10631, 10632, 0}, + {10632, 10631, 1}, + {10633, 10634, 0}, + {10634, 10633, 1}, + {10635, 10636, 0}, + {10636, 10635, 1}, + {10637, 10640, 0}, + {10638, 10639, 1}, + {10639, 10638, 0}, + {10640, 10637, 1}, + {10641, 10642, 0}, + {10642, 10641, 1}, + {10643, 10644, 0}, + {10644, 10643, 1}, + {10645, 10646, 0}, + {10646, 10645, 1}, + {10647, 10648, 0}, + {10648, 10647, 1}, + {10712, 10713, 0}, + {10713, 10712, 1}, + {10714, 10715, 0}, + {10715, 10714, 1}, + {10748, 10749, 0}, + {10749, 10748, 1}, + {11810, 11811, 0}, + {11811, 11810, 1}, + {11812, 11813, 0}, + {11813, 11812, 1}, + {11814, 11815, 0}, + {11815, 11814, 1}, + {11816, 11817, 0}, + {11817, 11816, 1}, + {12296, 12297, 0}, + {12297, 12296, 1}, + {12298, 12299, 0}, + {12299, 12298, 1}, + {12300, 12301, 0}, + {12301, 12300, 1}, + {12302, 12303, 0}, + {12303, 12302, 1}, + {12304, 12305, 0}, + {12305, 12304, 1}, + {12308, 12309, 0}, + {12309, 12308, 1}, + {12310, 12311, 0}, + {12311, 12310, 1}, + {12312, 12313, 0}, + {12313, 12312, 1}, + {12314, 12315, 0}, + {12315, 12314, 1}, + {65113, 65114, 0}, + {65114, 65113, 1}, + {65115, 65116, 0}, + {65116, 65115, 1}, + {65117, 65118, 0}, + {65118, 65117, 1}, + {65288, 65289, 0}, + {65289, 65288, 1}, + {65339, 65341, 0}, + {65341, 65339, 1}, + {65371, 65373, 0}, + {65373, 65371, 1}, + {65375, 65376, 0}, + {65376, 65375, 1}, + {65378, 65379, 0}, + {65379, 65378, 1}, +}; + /* Reindexing of NFC first characters. */ #define TOTAL_FIRST 376 #define TOTAL_LAST 62 @@ -1585,6 +1887,12 @@ static const Reindex nfc_last[] = { #define UCDN_SCRIPT_MULTANI 129 #define UCDN_SCRIPT_OLD_HUNGARIAN 130 #define UCDN_SCRIPT_SIGNWRITING 131 +#define UCDN_SCRIPT_ADLAM 132 +#define UCDN_SCRIPT_BHAIKSUKI 133 +#define UCDN_SCRIPT_MARCHEN 134 +#define UCDN_SCRIPT_NEWA 135 +#define UCDN_SCRIPT_OSAGE 136 +#define UCDN_SCRIPT_TANGUT 137 #define UCDN_GENERAL_CATEGORY_CC 0 #define UCDN_GENERAL_CATEGORY_CF 1 @@ -1654,26 +1962,27 @@ static const unsigned char index0[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 54, 55, 56, 56, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 67, 67, 67, - 67, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 52, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 88, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 88, 99, 88, 88, 88, 88, 88, 100, 100, - 100, 101, 102, 103, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 104, 104, - 104, 104, 105, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 106, 106, 107, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 108, 108, 109, 110, 88, 88, 88, 111, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 112, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 113, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 122, 123, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 124, 88, 88, 88, 88, 88, 125, 88, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 88, 88, 88, 88, 88, 88, 52, 52, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, + 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, + 66, 67, 68, 69, 70, 71, 65, 66, 67, 68, 69, 70, 71, 65, 72, 73, 73, 73, + 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 52, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 94, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 94, 105, 94, 106, 94, 94, 94, 107, + 107, 107, 108, 109, 110, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 111, + 111, 112, 113, 114, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 115, 116, 117, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 118, 118, 119, 120, 94, 94, 94, 121, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 123, 122, 122, 124, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 125, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 126, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 135, 136, 94, 94, 94, 94, 94, 137, 94, 94, 94, 94, 94, 94, 94, 138, 139, + 94, 94, 94, 94, 140, 94, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 151, 151, 151, 151, 152, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -1682,216 +1991,216 @@ static const unsigned char index0[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 136, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 137, 138, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 52, 52, 141, 140, 140, 140, 140, 142, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 142, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 143, 144, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 145, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 145, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 153, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 154, 155, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 156, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 52, 52, + 158, 157, 157, 157, 157, 159, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 159, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 160, 161, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 162, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 162, }; static const unsigned short index1[] = { @@ -1912,992 +2221,1135 @@ static const unsigned short index1[] = { 146, 147, 148, 149, 128, 128, 128, 128, 128, 128, 150, 150, 150, 150, 151, 152, 153, 120, 154, 155, 156, 156, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 165, 166, 167, 167, 167, 168, 120, 120, 120, 120, - 120, 120, 120, 120, 128, 128, 169, 120, 120, 120, 120, 120, 170, 171, - 172, 173, 174, 175, 175, 175, 175, 175, 175, 176, 177, 178, 179, 175, - 180, 181, 182, 175, 183, 184, 185, 186, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 120, 212, 213, 214, 215, 215, 216, - 217, 218, 219, 220, 221, 120, 222, 223, 224, 225, 226, 227, 228, 229, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 120, 240, 241, - 242, 243, 244, 241, 245, 246, 247, 248, 249, 120, 250, 251, 252, 253, - 254, 255, 256, 257, 257, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 120, 265, 266, 267, 268, 269, 269, 268, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 120, 279, 280, 281, 282, 282, 282, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 293, 293, 296, 297, - 294, 298, 299, 300, 301, 302, 303, 120, 304, 305, 305, 305, 305, 305, - 306, 307, 308, 309, 310, 311, 120, 120, 120, 120, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 120, 120, 120, 120, 324, 325, - 326, 327, 328, 329, 330, 331, 332, 333, 332, 332, 332, 334, 335, 336, - 337, 338, 339, 340, 339, 339, 339, 341, 342, 343, 344, 345, 120, 120, - 120, 120, 346, 346, 346, 346, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 346, 357, 358, 350, 359, 360, 360, 360, 360, 361, 362, - 363, 363, 363, 363, 363, 364, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 367, 367, 367, 367, - 367, 367, 367, 367, 367, 368, 369, 368, 367, 367, 367, 367, 367, 368, - 367, 367, 367, 367, 368, 369, 368, 367, 369, 367, 367, 367, 367, 367, - 367, 367, 368, 367, 367, 367, 367, 367, 367, 367, 367, 370, 371, 372, - 373, 374, 367, 367, 375, 376, 377, 377, 377, 377, 377, 377, 377, 377, - 377, 377, 378, 379, 380, 381, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 382, 381, 381, - 383, 384, 384, 385, 386, 386, 386, 386, 386, 386, 386, 386, 386, 387, - 388, 389, 390, 391, 392, 120, 393, 393, 394, 120, 395, 395, 396, 120, - 397, 398, 399, 120, 400, 400, 400, 400, 400, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 415, 415, 415, - 416, 415, 415, 415, 415, 415, 415, 120, 415, 415, 415, 415, 415, 417, - 381, 381, 381, 381, 381, 381, 381, 381, 418, 120, 419, 419, 419, 420, - 421, 422, 423, 424, 425, 426, 427, 427, 427, 428, 429, 120, 430, 430, - 430, 430, 430, 431, 430, 430, 430, 432, 433, 434, 435, 435, 435, 435, - 436, 436, 437, 438, 439, 439, 439, 439, 439, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 446, 447, 448, 449, 450, 451, 120, 120, 120, 120, - 120, 120, 120, 120, 452, 453, 453, 453, 453, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 465, 465, 466, 467, 468, 469, - 470, 470, 470, 470, 471, 472, 473, 474, 475, 475, 475, 475, 476, 477, - 478, 479, 480, 481, 482, 483, 484, 484, 484, 485, 120, 120, 120, 120, - 120, 120, 120, 120, 486, 120, 487, 488, 489, 490, 491, 492, 54, 54, 54, - 54, 493, 494, 56, 56, 56, 56, 56, 495, 496, 497, 54, 498, 54, 54, 54, - 499, 56, 56, 56, 500, 501, 502, 503, 504, 504, 504, 505, 506, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 507, 508, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 509, 510, 511, 512, 509, 510, - 509, 510, 511, 512, 509, 513, 509, 510, 509, 511, 509, 514, 509, 514, - 509, 514, 515, 516, 517, 518, 519, 520, 509, 521, 522, 523, 524, 525, - 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, - 540, 541, 56, 542, 543, 544, 543, 545, 120, 120, 546, 547, 548, 549, 550, - 120, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, - 564, 563, 565, 566, 567, 568, 569, 570, 571, 572, 573, 572, 574, 575, - 572, 576, 572, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, - 588, 589, 590, 591, 592, 587, 587, 593, 594, 595, 596, 597, 587, 587, - 598, 578, 599, 600, 587, 587, 601, 587, 587, 572, 602, 603, 572, 604, - 605, 606, 607, 607, 607, 607, 607, 607, 607, 607, 608, 572, 572, 609, - 610, 578, 578, 611, 572, 572, 572, 572, 577, 612, 572, 572, 613, 572, - 572, 572, 572, 614, 120, 120, 120, 572, 613, 120, 120, 615, 615, 615, - 615, 615, 616, 616, 617, 618, 618, 618, 618, 618, 618, 618, 618, 618, - 619, 615, 615, 620, 620, 620, 620, 620, 620, 620, 620, 620, 621, 620, - 620, 620, 620, 621, 572, 620, 620, 622, 572, 623, 573, 624, 625, 626, - 627, 573, 572, 622, 576, 572, 578, 628, 629, 625, 630, 572, 572, 572, - 572, 631, 572, 572, 572, 632, 633, 572, 572, 572, 572, 572, 634, 572, - 635, 572, 634, 636, 637, 620, 620, 638, 620, 620, 620, 572, 572, 572, - 572, 572, 572, 572, 639, 572, 572, 576, 572, 572, 640, 641, 615, 642, - 642, 643, 572, 572, 572, 572, 572, 644, 645, 646, 647, 648, 649, 578, - 578, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, - 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, - 650, 650, 650, 650, 650, 578, 578, 578, 578, 578, 578, 578, 578, 578, - 578, 578, 578, 578, 578, 578, 578, 651, 652, 652, 653, 587, 587, 578, - 654, 601, 655, 656, 657, 658, 659, 660, 661, 578, 662, 587, 663, 664, - 665, 666, 647, 578, 578, 590, 654, 666, 667, 668, 669, 587, 587, 587, - 587, 670, 671, 587, 587, 587, 587, 672, 673, 674, 647, 675, 676, 572, - 572, 572, 572, 572, 572, 578, 578, 677, 678, 679, 573, 572, 572, 680, - 572, 572, 572, 681, 572, 572, 572, 572, 682, 572, 683, 684, 120, 120, - 685, 120, 120, 686, 686, 686, 686, 686, 687, 688, 688, 688, 688, 688, - 689, 690, 691, 692, 693, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 694, 695, 696, 697, 698, 698, 698, 698, 699, 700, 701, 701, 701, 701, - 701, 701, 701, 702, 703, 704, 367, 367, 369, 120, 369, 369, 369, 369, - 369, 369, 369, 369, 705, 705, 705, 705, 706, 707, 708, 709, 710, 711, - 533, 712, 713, 120, 120, 120, 120, 120, 120, 120, 714, 714, 714, 715, - 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 716, 120, 714, 714, - 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, - 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 717, 120, 120, 120, - 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 729, 729, - 729, 729, 729, 729, 729, 729, 730, 731, 732, 733, 733, 733, 733, 733, - 733, 733, 733, 733, 733, 734, 735, 736, 736, 736, 736, 737, 738, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 739, 740, 741, 736, 736, - 736, 742, 718, 718, 718, 718, 719, 120, 733, 733, 743, 743, 743, 744, - 745, 746, 741, 741, 741, 747, 748, 749, 743, 743, 743, 750, 745, 746, - 741, 741, 741, 741, 751, 749, 741, 752, 753, 753, 753, 753, 753, 754, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 741, 741, 741, - 755, 756, 741, 741, 741, 741, 741, 741, 741, 741, 741, 741, 741, 757, - 741, 741, 741, 755, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 759, 760, 572, 572, 572, 572, 572, 572, 572, 572, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 759, 760, 760, 760, - 760, 760, 761, 761, 762, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 763, - 764, 764, 764, 764, 764, 764, 765, 120, 766, 766, 766, 766, 766, 767, - 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, - 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, - 768, 768, 768, 768, 768, 769, 768, 768, 770, 771, 120, 120, 101, 101, - 101, 101, 101, 772, 773, 774, 101, 101, 101, 775, 776, 776, 776, 776, - 776, 776, 776, 776, 777, 778, 779, 120, 64, 64, 780, 781, 782, 27, 783, - 27, 27, 27, 27, 27, 27, 27, 784, 785, 27, 786, 787, 27, 27, 788, 789, - 120, 120, 120, 120, 120, 120, 120, 790, 791, 792, 793, 794, 794, 795, - 796, 797, 798, 799, 799, 799, 799, 799, 799, 800, 120, 801, 802, 802, - 802, 802, 802, 803, 804, 805, 806, 807, 808, 809, 809, 810, 811, 812, - 813, 814, 814, 815, 816, 817, 817, 818, 819, 820, 821, 365, 365, 365, - 822, 823, 824, 824, 824, 824, 824, 825, 826, 827, 828, 829, 830, 831, - 346, 350, 832, 833, 833, 833, 833, 833, 834, 835, 120, 836, 837, 838, - 839, 346, 346, 840, 841, 842, 842, 842, 842, 842, 842, 843, 844, 845, - 120, 120, 846, 847, 848, 849, 120, 850, 850, 850, 120, 369, 369, 54, 54, - 54, 54, 54, 851, 852, 120, 853, 853, 853, 853, 853, 853, 853, 853, 853, - 853, 847, 847, 847, 847, 854, 855, 856, 857, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 858, 120, 366, 366, 859, 860, 366, 366, 366, - 366, 366, 861, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, - 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, - 862, 862, 862, 862, 862, 862, 862, 863, 863, 863, 863, 863, 863, 863, - 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, - 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 759, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 864, 760, 760, 760, - 760, 865, 120, 866, 867, 121, 868, 869, 870, 871, 121, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 872, 873, 874, 120, 875, + 120, 120, 120, 120, 128, 128, 169, 170, 120, 120, 171, 126, 172, 173, + 174, 175, 176, 177, 177, 177, 177, 177, 177, 178, 179, 180, 181, 177, + 182, 183, 184, 177, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 120, 214, 215, 216, 217, 217, 218, + 219, 220, 221, 222, 223, 120, 224, 225, 226, 227, 228, 229, 230, 231, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 120, 242, 243, + 244, 245, 246, 243, 247, 248, 249, 250, 251, 120, 252, 253, 254, 255, + 256, 257, 258, 259, 259, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 120, 267, 268, 269, 270, 271, 271, 270, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 120, 281, 282, 283, 284, 284, 284, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 295, 295, 298, 299, + 296, 300, 301, 302, 303, 304, 305, 120, 306, 307, 307, 307, 307, 307, + 308, 309, 310, 311, 312, 313, 120, 120, 120, 120, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 120, 120, 120, 120, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, 334, 334, 334, 336, 337, 338, + 339, 340, 341, 342, 341, 341, 341, 343, 344, 345, 346, 347, 120, 120, + 120, 120, 348, 348, 348, 348, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 348, 359, 360, 352, 361, 362, 362, 362, 362, 363, 364, + 365, 365, 365, 365, 365, 366, 367, 367, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 368, 368, 368, 368, 368, 368, 368, 368, 368, 369, + 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 370, 370, 370, 370, + 370, 370, 370, 370, 370, 371, 372, 371, 370, 370, 370, 370, 370, 371, + 370, 370, 370, 370, 371, 372, 371, 370, 372, 370, 370, 370, 370, 370, + 370, 370, 371, 370, 370, 370, 370, 370, 370, 370, 370, 373, 374, 375, + 376, 377, 370, 370, 378, 379, 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 381, 382, 383, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 384, 384, + 386, 387, 387, 388, 389, 389, 389, 389, 389, 389, 389, 389, 389, 390, + 391, 392, 393, 394, 395, 120, 396, 396, 397, 120, 398, 398, 399, 120, + 400, 401, 402, 120, 403, 403, 403, 403, 403, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 418, 418, 418, + 419, 418, 418, 418, 418, 418, 418, 120, 420, 418, 418, 418, 418, 421, + 384, 384, 384, 384, 384, 384, 384, 384, 422, 120, 423, 423, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 431, 431, 432, 433, 120, 434, 434, + 434, 434, 434, 435, 434, 434, 434, 436, 437, 438, 439, 439, 439, 439, + 440, 440, 441, 442, 443, 443, 443, 443, 443, 443, 444, 445, 446, 447, + 448, 449, 450, 451, 450, 451, 452, 453, 454, 455, 120, 120, 120, 120, + 120, 120, 120, 120, 456, 457, 457, 457, 457, 457, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 469, 469, 470, 471, 472, 473, + 474, 474, 474, 474, 475, 476, 477, 478, 479, 479, 479, 479, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 488, 488, 489, 100, 490, 120, 120, + 120, 120, 120, 120, 491, 120, 492, 493, 494, 495, 496, 497, 54, 54, 54, + 54, 498, 499, 56, 56, 56, 56, 56, 500, 501, 502, 54, 503, 54, 54, 54, + 504, 56, 56, 56, 505, 506, 507, 508, 509, 509, 509, 510, 511, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 512, 513, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 514, 515, 516, 517, 514, 515, + 514, 515, 516, 517, 514, 518, 514, 515, 514, 516, 514, 519, 514, 519, + 514, 519, 520, 521, 522, 523, 524, 525, 514, 526, 527, 528, 529, 530, + 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, + 545, 546, 56, 547, 548, 549, 550, 551, 552, 552, 553, 554, 555, 556, 557, + 120, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, + 571, 570, 572, 573, 574, 575, 576, 577, 578, 579, 580, 579, 581, 582, + 579, 583, 579, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, + 595, 596, 597, 598, 599, 594, 594, 600, 601, 602, 603, 604, 594, 594, + 605, 585, 606, 607, 594, 594, 608, 594, 594, 579, 609, 610, 611, 612, + 613, 614, 615, 615, 615, 615, 615, 615, 615, 615, 616, 579, 579, 617, + 618, 585, 585, 619, 579, 579, 579, 579, 584, 620, 621, 622, 623, 579, + 579, 579, 579, 623, 120, 120, 120, 579, 624, 120, 120, 625, 625, 625, + 625, 625, 626, 626, 627, 628, 628, 628, 628, 628, 628, 628, 628, 628, + 629, 625, 630, 631, 631, 631, 631, 631, 631, 631, 631, 631, 632, 631, + 631, 631, 631, 633, 579, 631, 631, 634, 579, 635, 636, 637, 638, 639, + 640, 636, 579, 634, 641, 579, 642, 643, 644, 645, 646, 579, 579, 579, + 647, 648, 649, 650, 579, 651, 652, 579, 653, 579, 579, 654, 655, 656, + 657, 579, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 579, + 579, 579, 669, 579, 670, 579, 671, 672, 673, 674, 675, 676, 625, 677, + 677, 678, 579, 579, 579, 669, 679, 680, 681, 682, 683, 684, 685, 585, + 585, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, + 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, + 686, 686, 686, 686, 686, 585, 585, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 585, 585, 585, 687, 688, 688, 689, 594, 594, 585, + 690, 691, 692, 693, 694, 695, 696, 697, 698, 585, 699, 594, 700, 701, + 702, 703, 683, 585, 585, 597, 690, 703, 704, 705, 706, 594, 594, 594, + 594, 707, 708, 594, 594, 594, 594, 709, 710, 711, 683, 712, 713, 579, + 579, 579, 714, 579, 579, 585, 585, 715, 716, 717, 636, 579, 579, 718, + 579, 579, 579, 719, 579, 579, 579, 579, 720, 579, 721, 722, 120, 120, + 723, 120, 120, 724, 724, 724, 724, 724, 725, 726, 726, 726, 726, 726, + 727, 728, 729, 730, 731, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 732, 733, 734, 735, 736, 736, 736, 736, 737, 738, 739, 739, 739, 739, + 739, 739, 739, 740, 741, 742, 370, 370, 372, 120, 372, 372, 372, 372, + 372, 372, 372, 372, 743, 743, 743, 743, 744, 745, 746, 747, 748, 749, + 750, 751, 752, 120, 120, 120, 120, 120, 120, 120, 753, 753, 753, 754, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 755, 120, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 756, 120, 120, 120, + 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 769, + 770, 769, 769, 769, 771, 772, 773, 774, 775, 776, 777, 777, 778, 777, + 777, 777, 779, 780, 781, 782, 783, 784, 784, 784, 784, 785, 786, 787, + 787, 787, 787, 787, 787, 787, 787, 787, 787, 788, 789, 790, 784, 784, + 784, 791, 757, 757, 757, 757, 758, 120, 792, 792, 793, 793, 793, 794, + 795, 796, 790, 790, 790, 797, 798, 799, 793, 793, 793, 800, 795, 796, + 790, 790, 790, 790, 801, 799, 790, 802, 803, 803, 803, 803, 803, 804, + 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 790, 790, 790, + 805, 806, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 807, + 790, 790, 790, 805, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 809, 810, 579, 579, 579, 579, 579, 579, 579, 579, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 809, 810, 810, 810, + 810, 810, 811, 811, 812, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 813, + 814, 814, 814, 814, 814, 814, 815, 120, 816, 816, 816, 816, 816, 817, + 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, + 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, + 818, 818, 818, 818, 818, 819, 818, 818, 820, 821, 120, 120, 101, 101, + 101, 101, 101, 822, 823, 824, 101, 101, 101, 825, 826, 826, 826, 826, + 826, 826, 826, 826, 827, 828, 829, 120, 64, 64, 830, 831, 832, 27, 833, + 27, 27, 27, 27, 27, 27, 27, 834, 835, 27, 836, 837, 27, 27, 838, 839, + 120, 120, 120, 120, 120, 120, 120, 840, 841, 842, 843, 844, 844, 845, + 846, 847, 848, 849, 849, 849, 849, 849, 849, 850, 120, 851, 852, 852, + 852, 852, 852, 853, 854, 855, 856, 857, 858, 859, 859, 860, 861, 862, + 863, 864, 864, 865, 866, 867, 867, 868, 869, 870, 871, 367, 367, 367, + 872, 873, 874, 874, 874, 874, 874, 875, 876, 877, 878, 879, 880, 881, + 348, 352, 882, 883, 883, 883, 883, 883, 884, 885, 120, 886, 887, 888, + 889, 348, 348, 890, 891, 892, 892, 892, 892, 892, 892, 893, 894, 895, + 120, 120, 896, 897, 898, 899, 120, 900, 900, 900, 120, 372, 372, 54, 54, + 54, 54, 54, 901, 902, 120, 903, 903, 903, 903, 903, 903, 903, 903, 903, + 903, 897, 897, 897, 897, 904, 905, 906, 907, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, + 909, 909, 908, 909, 909, 910, 909, 909, 909, 909, 909, 909, 908, 909, + 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, + 909, 911, 120, 368, 368, 912, 913, 369, 369, 369, 369, 369, 914, 915, + 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, + 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, + 915, 915, 915, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 916, 916, 916, 916, 916, 916, 916, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 809, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 917, 810, 810, 810, 810, 918, 120, 919, + 920, 121, 921, 922, 923, 924, 121, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 925, 926, 927, 120, 928, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 876, 120, 120, 128, 128, 128, 128, 128, 128, 128, 128, 877, - 128, 128, 128, 128, 128, 128, 120, 120, 120, 120, 120, 128, 878, 879, - 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 893, 894, 895, 896, 897, 898, 899, 899, 900, 901, 902, 902, - 903, 904, 905, 906, 905, 905, 905, 905, 907, 908, 908, 908, 909, 910, - 910, 910, 911, 912, 913, 120, 914, 915, 916, 915, 915, 917, 915, 915, - 918, 915, 919, 915, 919, 120, 120, 120, 120, 915, 915, 915, 915, 915, - 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 920, 921, 922, 922, - 922, 922, 922, 923, 607, 924, 924, 924, 924, 924, 924, 925, 926, 927, - 928, 572, 929, 930, 120, 120, 120, 120, 120, 607, 607, 607, 607, 607, - 931, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 932, 932, 932, 933, 934, 934, 934, 934, 934, 934, 935, - 120, 936, 937, 937, 938, 939, 939, 939, 939, 940, 120, 941, 941, 942, - 943, 944, 944, 944, 944, 945, 946, 947, 947, 947, 948, 949, 949, 949, - 949, 950, 949, 951, 120, 120, 120, 120, 120, 952, 952, 952, 952, 952, - 953, 953, 953, 953, 953, 954, 954, 954, 954, 954, 954, 955, 955, 955, - 956, 957, 958, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 959, - 959, 959, 959, 959, 120, 960, 960, 960, 960, 960, 960, 961, 962, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, - 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, - 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 964, - 120, 963, 963, 965, 120, 963, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 966, 967, 968, - 968, 968, 968, 969, 970, 971, 971, 972, 973, 974, 974, 975, 976, 977, - 977, 977, 978, 979, 980, 120, 120, 120, 120, 120, 120, 981, 981, 982, - 983, 984, 984, 985, 986, 987, 987, 987, 988, 120, 120, 120, 120, 120, - 120, 120, 120, 989, 989, 989, 989, 990, 990, 990, 991, 992, 992, 993, - 992, 992, 992, 992, 992, 994, 995, 996, 997, 998, 998, 999, 1000, 1001, - 120, 1002, 1003, 1004, 1004, 1004, 1005, 1006, 1006, 1006, 1007, 120, - 120, 120, 120, 1008, 1009, 1008, 1008, 1010, 1011, 1012, 120, 1013, 1013, - 1013, 1013, 1013, 1013, 1014, 1015, 1016, 1016, 1017, 1018, 1019, 1019, - 1020, 1021, 1022, 1022, 1023, 1024, 120, 1025, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, - 1026, 1027, 120, 120, 120, 120, 120, 120, 1028, 1028, 1028, 1028, 1028, - 1028, 1029, 120, 1030, 1030, 1030, 1030, 1030, 1030, 1031, 1032, 120, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 929, 120, + 120, 128, 128, 128, 128, 128, 128, 128, 128, 930, 128, 128, 128, 128, + 128, 128, 120, 120, 120, 120, 120, 128, 931, 932, 932, 933, 934, 935, + 936, 937, 938, 939, 940, 941, 942, 943, 944, 169, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 945, 946, + 947, 948, 949, 950, 951, 951, 952, 953, 954, 954, 955, 956, 957, 958, + 959, 959, 959, 959, 960, 961, 961, 961, 962, 963, 963, 963, 964, 965, + 966, 120, 967, 968, 969, 968, 968, 970, 968, 968, 971, 968, 972, 968, + 972, 120, 120, 120, 120, 968, 968, 968, 968, 968, 968, 968, 968, 968, + 968, 968, 968, 968, 968, 968, 973, 974, 975, 975, 975, 975, 975, 976, + 615, 977, 977, 977, 977, 977, 977, 978, 979, 980, 981, 579, 982, 983, + 120, 120, 120, 120, 120, 615, 615, 615, 615, 615, 984, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 985, + 985, 985, 986, 987, 987, 987, 987, 987, 987, 988, 120, 989, 990, 990, + 991, 992, 992, 992, 992, 993, 120, 994, 994, 995, 996, 997, 997, 997, + 997, 998, 999, 1000, 1000, 1000, 1001, 1002, 1002, 1002, 1002, 1003, + 1002, 1004, 120, 120, 120, 120, 120, 1005, 1005, 1005, 1005, 1005, 1006, + 1006, 1006, 1006, 1006, 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008, + 1008, 1009, 1010, 1011, 1012, 1012, 1012, 1012, 1013, 1014, 1014, 1014, + 1014, 1015, 1016, 1016, 1016, 1016, 1016, 120, 1017, 1017, 1017, 1017, + 1017, 1017, 1018, 1019, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1021, 120, 1020, + 1020, 1022, 120, 1020, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 1023, 1024, 1025, 1025, + 1025, 1025, 1026, 1027, 1028, 1028, 1029, 1030, 1031, 1031, 1032, 1033, + 1034, 1034, 1034, 1035, 1036, 1037, 120, 120, 120, 120, 120, 120, 1038, + 1038, 1039, 1040, 1041, 1041, 1042, 1043, 1044, 1044, 1044, 1045, 120, + 120, 120, 120, 120, 120, 120, 120, 1046, 1046, 1046, 1046, 1047, 1047, + 1047, 1048, 1049, 1049, 1050, 1049, 1049, 1049, 1049, 1049, 1051, 1052, + 1053, 1054, 1055, 1055, 1056, 1057, 1058, 120, 1059, 1060, 1061, 1061, + 1061, 1062, 1063, 1063, 1063, 1064, 120, 120, 120, 120, 1065, 1066, 1065, + 1065, 1067, 1068, 1069, 120, 1070, 1070, 1070, 1070, 1070, 1070, 1071, + 1072, 1073, 1073, 1074, 1075, 1076, 1076, 1077, 1078, 1079, 1079, 1080, + 1081, 120, 1082, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1083, + 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1084, 120, 120, 120, 120, + 120, 120, 1085, 1085, 1085, 1085, 1085, 1085, 1086, 120, 1087, 1087, + 1087, 1087, 1087, 1087, 1088, 1089, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 1090, 1090, 1090, 1091, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 1033, 1033, 1033, 1034, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 1035, 1036, 1036, 1036, 1036, 1036, - 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 120, 1044, 1045, 1046, - 1046, 1046, 1046, 1046, 1047, 1048, 1049, 120, 1050, 1050, 1050, 1051, - 1052, 1053, 1054, 1055, 1055, 1055, 1056, 1057, 1058, 1059, 1060, 120, - 1061, 1061, 1061, 1061, 1062, 120, 1063, 1064, 1064, 1064, 1064, 1064, - 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 120, 1074, 1074, - 1075, 1074, 1074, 1076, 1077, 1078, 120, 120, 120, 120, 120, 120, 120, - 120, 1079, 1080, 1081, 1082, 1081, 1083, 1084, 1084, 1084, 1084, 1084, - 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1093, 1094, 1095, - 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1102, 120, 120, 120, 120, 120, + 120, 1092, 1093, 1093, 1093, 1093, 1093, 1093, 1094, 1095, 1096, 1097, + 1098, 1099, 1100, 120, 1101, 1102, 1103, 1103, 1103, 1103, 1103, 1104, + 1105, 1106, 120, 1107, 1107, 1107, 1108, 1109, 1110, 1111, 1112, 1112, + 1112, 1113, 1114, 1115, 1116, 1117, 120, 1118, 1118, 1118, 1118, 1119, + 120, 1120, 1121, 1121, 1121, 1121, 1121, 1122, 1123, 1124, 1125, 1126, + 1127, 1128, 1129, 1130, 120, 1131, 1131, 1132, 1131, 1131, 1133, 1134, + 1135, 120, 120, 120, 120, 120, 120, 120, 120, 1136, 1137, 1138, 1139, + 1138, 1140, 1141, 1141, 1141, 1141, 1141, 1142, 1143, 1144, 1145, 1146, + 1147, 1148, 1149, 1150, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, + 1158, 1159, 1159, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 1160, 1160, 1160, 1160, 1160, 1160, 1161, + 1162, 1163, 1164, 1165, 1166, 120, 120, 120, 120, 1167, 1167, 1167, 1167, + 1167, 1167, 1168, 1169, 1170, 120, 1171, 1172, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 1173, 1173, 1173, 1173, 1173, 1174, 1175, 1176, 1177, 1178, 1179, + 1180, 120, 120, 120, 120, 1181, 1181, 1181, 1181, 1181, 1181, 1182, 1183, + 1184, 120, 1185, 1186, 1187, 1188, 120, 120, 1189, 1189, 1189, 1189, + 1189, 1190, 1191, 120, 1192, 1193, 120, 120, 120, 120, 120, 120, 1194, + 1194, 1194, 1195, 1196, 1197, 1198, 1199, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 1103, 1103, 1103, 1103, 1103, 1103, 1104, 1105, 1106, 120, 1107, 1108, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1200, 1200, 1200, 1200, + 1201, 1201, 1201, 1201, 1202, 1203, 1204, 1205, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 1109, 1109, 1109, 1109, 1109, 1110, 1111, - 1112, 1113, 1114, 1114, 1115, 120, 120, 120, 120, 1116, 1116, 1116, 1116, - 1116, 1116, 1117, 1118, 1119, 120, 1120, 1121, 120, 120, 120, 120, 1122, - 1122, 1122, 1122, 1122, 1123, 1124, 120, 1125, 1126, 120, 120, 120, 120, - 120, 120, 1127, 1127, 1127, 1128, 1129, 1130, 1131, 1132, 120, 120, 120, + 120, 120, 120, 120, 120, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1207, + 1208, 1209, 1208, 1208, 1208, 1210, 1211, 1212, 1213, 120, 1214, 1215, + 1216, 1217, 1218, 1219, 1219, 1219, 1220, 1221, 1221, 1222, 1223, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 1224, 1224, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1225, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1226, 1226, 1226, + 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1227, 1228, + 120, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, + 1224, 1229, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1231, 1230, 1230, 1230, 1230, 1232, 1233, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1234, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1235, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1237, 1236, + 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, + 1236, 1238, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 826, 826, 826, + 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, + 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, + 826, 826, 826, 826, 826, 826, 826, 826, 1239, 1240, 1240, 1240, 1241, + 1242, 1243, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 1244, 1244, 1244, 1245, 1246, 120, 1247, 1247, 1247, 1247, 1247, 1247, + 1248, 1249, 1250, 120, 1251, 1252, 1253, 1247, 1247, 1254, 1247, 1247, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1133, - 1133, 1133, 1133, 1134, 1134, 1134, 1134, 1135, 1136, 1137, 1138, 120, + 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1256, 120, 1257, 1258, + 1258, 1258, 1258, 1259, 120, 1260, 1261, 1262, 120, 120, 120, 120, 120, + 120, 120, 120, 1263, 120, 120, 120, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1265, 120, 120, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, + 1264, 1264, 1264, 1264, 1266, 120, 1267, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 1139, 1139, 1139, 1139, - 1139, 1139, 1139, 1140, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1142, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 1143, 1143, 1143, 1143, 1143, 1143, - 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1144, 1145, 120, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, - 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1146, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1268, 1268, 1268, + 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1269, 1268, + 1270, 1268, 1271, 1268, 1272, 1273, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 615, 1274, 120, 615, 615, 615, 615, 1275, 1276, + 615, 615, 615, 615, 615, 615, 1277, 1278, 1279, 1280, 1281, 1282, 615, + 615, 615, 1283, 615, 615, 615, 615, 615, 615, 615, 1284, 120, 120, 980, + 980, 980, 980, 980, 980, 980, 980, 1285, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 1147, 1147, 1147, 1147, 1147, - 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, - 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, - 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1148, 120, 120, 120, 120, + 120, 120, 120, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 623, + 120, 975, 975, 1286, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 1287, 1287, 1287, 1288, 1289, 1289, + 1290, 1287, 1287, 1291, 1292, 1289, 1289, 1287, 1287, 1287, 1288, 1289, + 1289, 1293, 1294, 1295, 1291, 1296, 1297, 1289, 1287, 1287, 1287, 1288, + 1289, 1289, 1298, 1299, 1300, 1301, 1289, 1289, 1289, 1302, 1303, 1304, + 1305, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, 1287, 1287, + 1287, 1288, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, 1287, + 1287, 1287, 1288, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, + 1287, 1287, 1287, 1288, 1289, 1289, 1306, 1287, 1287, 1287, 1307, 1289, + 1289, 1308, 1309, 1287, 1287, 1310, 1289, 1289, 1311, 1290, 1287, 1287, + 1312, 1289, 1289, 1313, 1314, 1287, 1287, 1315, 1289, 1289, 1289, 1316, + 1287, 1287, 1287, 1307, 1289, 1289, 1308, 1317, 1318, 1318, 1318, 1318, + 1318, 1318, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, + 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, + 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1320, 1320, + 1320, 1320, 1320, 1320, 1321, 1322, 1320, 1320, 1320, 1320, 1320, 1323, + 1324, 1319, 1325, 1326, 120, 1327, 1328, 1320, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 1329, 1330, 1330, 1331, 1332, 1333, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 1149, 1149, 1149, 1149, 1149, - 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, - 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, - 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1150, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1334, 1334, 1334, 1334, + 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, + 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1335, 1336, 1337, 120, + 120, 120, 120, 120, 1338, 1338, 1338, 1338, 1339, 1340, 1340, 1340, 1341, + 1342, 1343, 1344, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 1345, 128, 128, 128, 1346, + 1347, 1348, 1349, 1350, 1351, 1346, 1352, 1346, 1348, 1348, 1353, 128, + 1354, 128, 1355, 1356, 1354, 128, 1355, 120, 120, 120, 120, 120, 120, + 1357, 120, 1358, 1359, 1359, 1359, 1359, 1360, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1360, 1361, 1359, 1362, + 1363, 1359, 1363, 1364, 1363, 1359, 1359, 1359, 1365, 1361, 626, 1366, + 628, 628, 628, 1367, 628, 628, 628, 628, 628, 628, 628, 1368, 628, 628, + 628, 1369, 1370, 1371, 628, 1372, 1361, 1361, 1361, 1361, 1361, 1361, + 1373, 1374, 1374, 1374, 1375, 1361, 790, 790, 790, 790, 790, 1376, 790, + 1377, 1378, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 757, + 757, 757, 757, 1379, 1380, 1381, 757, 757, 757, 757, 757, 757, 757, 757, + 1382, 1383, 757, 1384, 1385, 757, 757, 1386, 1387, 1388, 1389, 1384, + 1359, 757, 757, 1390, 1391, 757, 757, 757, 757, 757, 757, 757, 1392, + 1393, 1394, 1395, 757, 1396, 1397, 1394, 1398, 1399, 757, 757, 757, 1400, + 1401, 1402, 757, 757, 757, 757, 757, 757, 757, 757, 1403, 1404, 757, + 1405, 649, 1406, 757, 1407, 1408, 579, 1409, 757, 757, 757, 1359, 1410, + 1411, 1359, 1359, 1412, 1359, 1358, 1359, 1359, 1359, 1359, 1359, 1413, + 1414, 1359, 1359, 1413, 1415, 757, 757, 757, 757, 757, 757, 757, 757, + 1416, 1417, 579, 579, 579, 579, 1418, 1419, 757, 757, 757, 757, 1420, + 757, 1421, 757, 1422, 1358, 1423, 1361, 1359, 1424, 1425, 1361, 579, 579, + 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 1426, 1361, + 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 1427, 1361, 1361, 1361, + 1361, 1361, 579, 1426, 579, 579, 579, 579, 579, 579, 579, 1361, 579, + 1428, 579, 579, 579, 579, 579, 1361, 579, 579, 579, 1429, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 757, 1430, + 1431, 1361, 1432, 1433, 757, 1434, 757, 1435, 1361, 1361, 1361, 1361, + 757, 757, 1436, 1361, 1361, 1361, 1361, 1361, 1437, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, + 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1438, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 1439, 810, 810, 810, 810, 810, 808, + 808, 808, 808, 808, 808, 1440, 810, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 809, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 917, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 808, 808, 808, 809, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 810, 1441, 1442, 120, 120, 120, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 776, 776, 776, 776, 776, - 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, - 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, - 776, 776, 776, 776, 776, 776, 1151, 1152, 1152, 1152, 1153, 1154, 1155, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1156, 1156, - 1156, 1157, 1158, 120, 1159, 1159, 1159, 1159, 1159, 1159, 1160, 1161, - 1162, 120, 1163, 1164, 1165, 1159, 1159, 1166, 1159, 1159, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1167, 1167, 1167, - 1167, 1167, 1167, 1167, 1167, 1168, 120, 1169, 1170, 1170, 1170, 1170, - 1171, 120, 1172, 1173, 1174, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 1175, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 1176, 1176, 1176, 1176, 1176, 1176, - 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1177, 1176, 1178, 1176, 1179, - 1176, 1180, 1181, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 1182, 120, 607, 607, 607, 607, 1183, 1184, 607, 607, 607, 607, - 607, 607, 1185, 1186, 1187, 1188, 1189, 1190, 607, 607, 607, 1191, 607, - 607, 607, 607, 607, 607, 607, 1192, 120, 120, 927, 927, 927, 927, 927, - 927, 927, 927, 1193, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 614, 120, 922, 922, 1194, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 1195, 1195, 1195, 1196, 1197, 1197, 1198, 1195, 1195, - 1199, 1200, 1197, 1197, 1195, 1195, 1195, 1196, 1197, 1197, 1201, 1202, - 1203, 1199, 1204, 1205, 1197, 1195, 1195, 1195, 1196, 1197, 1197, 1206, - 1207, 1208, 1209, 1197, 1197, 1197, 1210, 1211, 1212, 1213, 1197, 1197, - 1198, 1195, 1195, 1199, 1197, 1197, 1197, 1195, 1195, 1195, 1196, 1197, - 1197, 1198, 1195, 1195, 1199, 1197, 1197, 1197, 1195, 1195, 1195, 1196, - 1197, 1197, 1198, 1195, 1195, 1199, 1197, 1197, 1197, 1195, 1195, 1195, - 1196, 1197, 1197, 1214, 1195, 1195, 1195, 1215, 1197, 1197, 1216, 1217, - 1195, 1195, 1218, 1197, 1197, 1219, 1198, 1195, 1195, 1220, 1197, 1197, - 1221, 1222, 1195, 1195, 1223, 1197, 1197, 1197, 1224, 1195, 1195, 1195, - 1215, 1197, 1197, 1216, 1225, 1226, 1226, 1226, 1226, 1226, 1226, 1227, - 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, - 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1227, - 1227, 1227, 1227, 1227, 1227, 1227, 1227, 1228, 1228, 1228, 1228, 1228, - 1228, 1229, 1230, 1228, 1228, 1228, 1228, 1228, 1231, 1232, 1227, 1233, - 1234, 120, 1235, 1236, 1228, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, - 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, - 1237, 1238, 1239, 1240, 120, 120, 120, 120, 120, 1241, 128, 128, 128, - 1242, 1243, 1244, 1245, 1246, 1247, 1242, 1248, 1242, 1244, 1244, 1249, - 128, 1250, 128, 1251, 1252, 1250, 128, 1251, 120, 120, 120, 120, 120, - 120, 1253, 120, 572, 572, 572, 572, 572, 929, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 929, 120, 572, 614, 1254, 572, 1254, - 572, 1254, 572, 572, 572, 681, 120, 616, 1255, 618, 618, 618, 1256, 618, - 618, 618, 618, 618, 618, 618, 1257, 618, 618, 618, 618, 618, 1258, 120, - 120, 120, 120, 120, 120, 120, 120, 1259, 607, 607, 607, 1260, 120, 741, - 741, 741, 741, 741, 1261, 741, 1262, 1263, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 1264, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 1265, 572, 572, 572, - 572, 1266, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 1267, 120, 572, - 1268, 929, 120, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 572, 572, 929, 120, 572, 572, 572, 572, 572, 572, 572, 572, 572, - 572, 1268, 120, 120, 120, 120, 120, 572, 929, 572, 572, 572, 572, 572, - 572, 572, 120, 572, 684, 572, 572, 572, 572, 572, 120, 572, 572, 572, - 681, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 572, - 1267, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1268, - 120, 120, 120, 120, 120, 120, 120, 1267, 120, 120, 120, 120, 120, 120, - 120, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 1269, - 760, 760, 760, 760, 760, 758, 758, 758, 758, 758, 758, 1270, 760, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 759, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 864, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 758, 758, 758, 759, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, - 1271, 1272, 120, 120, 120, 1273, 1273, 1273, 1273, 1273, 1273, 1273, - 1273, 1273, 1273, 1273, 1273, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 879, 879, 879, 879, 879, 879, - 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, - 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 120, 120, 863, 863, - 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, - 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, 863, - 863, 1274, + 120, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, + 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, + 932, 932, 932, 120, 120, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 916, 916, 916, 916, 916, 916, 916, 916, 1444, }; static const unsigned short index2[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 4, 3, 1, 1, 1, 1, 1, 1, 3, 3, 3, 2, - 5, 6, 6, 7, 8, 7, 6, 6, 9, 10, 6, 11, 12, 13, 12, 12, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 12, 6, 15, 16, 15, 6, 6, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, 6, 10, 18, 19, 18, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 16, - 10, 16, 1, 1, 1, 1, 1, 1, 3, 1, 1, 21, 22, 8, 8, 23, 8, 24, 22, 25, 26, - 27, 28, 16, 29, 30, 18, 31, 32, 33, 33, 25, 34, 22, 22, 25, 33, 27, 35, - 36, 36, 36, 22, 37, 37, 37, 37, 37, 37, 38, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 38, 37, 37, 37, 37, 37, 37, 39, 38, 37, 37, 37, 37, 37, 38, 40, - 40, 40, 41, 41, 41, 41, 40, 41, 40, 40, 40, 41, 40, 40, 41, 41, 40, 41, - 40, 40, 41, 41, 41, 39, 40, 40, 40, 41, 40, 41, 40, 41, 37, 40, 37, 41, - 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 37, 40, 37, 40, 37, 41, - 37, 41, 37, 41, 37, 40, 37, 41, 37, 41, 37, 41, 37, 41, 37, 41, 38, 40, - 37, 40, 38, 40, 37, 41, 37, 41, 40, 37, 41, 37, 41, 37, 41, 38, 40, 38, - 40, 37, 40, 37, 41, 37, 40, 40, 38, 40, 37, 40, 37, 41, 37, 41, 38, 40, - 37, 41, 37, 41, 37, 37, 41, 37, 41, 37, 41, 41, 41, 37, 37, 41, 37, 41, - 37, 37, 41, 37, 37, 37, 41, 41, 37, 37, 37, 37, 41, 37, 37, 41, 37, 37, - 37, 41, 41, 41, 37, 37, 41, 37, 37, 41, 37, 41, 37, 41, 37, 37, 41, 37, - 41, 41, 37, 41, 37, 37, 41, 37, 37, 37, 41, 37, 41, 37, 37, 41, 41, 42, - 37, 41, 41, 41, 42, 42, 42, 42, 37, 43, 41, 37, 43, 41, 37, 43, 41, 37, - 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 37, 40, 41, 37, 41, - 41, 37, 43, 41, 37, 41, 37, 37, 37, 41, 37, 41, 41, 41, 41, 41, 41, 41, - 37, 37, 41, 37, 37, 41, 41, 37, 41, 37, 37, 37, 37, 41, 41, 40, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 41, - 41, 41, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, - 46, 46, 47, 47, 25, 47, 45, 48, 45, 48, 48, 48, 45, 48, 45, 45, 49, 46, - 47, 47, 47, 47, 47, 47, 25, 25, 25, 25, 47, 25, 47, 25, 44, 44, 44, 44, - 44, 47, 47, 47, 47, 47, 50, 50, 45, 47, 46, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53, 53, - 53, 53, 52, 54, 53, 53, 53, 53, 53, 55, 55, 53, 53, 53, 53, 55, 55, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 56, 56, 56, 56, 56, 53, 53, 53, - 53, 51, 51, 51, 51, 51, 51, 51, 51, 57, 51, 53, 53, 53, 51, 51, 51, 53, - 53, 58, 51, 51, 51, 53, 53, 53, 53, 51, 52, 53, 53, 51, 59, 60, 60, 59, - 60, 60, 59, 51, 51, 51, 51, 51, 61, 62, 61, 62, 45, 63, 61, 62, 64, 64, - 65, 62, 62, 62, 66, 61, 64, 64, 64, 64, 63, 47, 61, 66, 61, 61, 61, 64, - 61, 64, 61, 61, 62, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, - 67, 67, 67, 67, 64, 67, 67, 67, 67, 67, 67, 67, 61, 61, 62, 62, 62, 62, - 62, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 62, 68, 68, 68, 68, 68, 68, 68, 62, 62, 62, 62, 62, 61, 62, 62, 61, 61, - 61, 62, 62, 62, 61, 62, 61, 62, 61, 62, 61, 62, 61, 62, 69, 70, 69, 70, - 69, 70, 69, 70, 69, 70, 69, 70, 69, 70, 62, 62, 62, 62, 61, 62, 71, 61, - 62, 61, 61, 62, 62, 61, 61, 61, 72, 73, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, - 74, 74, 74, 74, 75, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 72, 75, 72, 75, 72, 75, 72, 75, 72, 75, 76, 77, 77, 78, 78, 77, - 79, 79, 72, 75, 72, 75, 72, 75, 72, 72, 75, 72, 75, 72, 75, 72, 75, 72, - 75, 72, 75, 72, 75, 75, 64, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 64, 64, 81, 82, 82, 82, 82, - 82, 82, 64, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 64, 84, 85, 64, 64, 86, 86, 87, 64, 88, 89, 89, 89, 89, 88, 89, 89, 89, - 90, 88, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89, 89, 88, 89, - 89, 90, 91, 89, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 107, 89, 88, 107, 100, 64, 64, 64, 64, 64, - 64, 64, 64, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 64, - 64, 64, 64, 64, 110, 110, 110, 107, 107, 64, 64, 64, 111, 111, 111, 111, - 111, 112, 113, 113, 114, 115, 115, 116, 117, 118, 119, 119, 120, 120, - 120, 120, 120, 120, 120, 120, 121, 122, 123, 124, 125, 64, 118, 124, 126, - 126, 126, 126, 126, 126, 126, 126, 127, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 128, 129, 130, 131, 132, 133, 134, 135, 78, 78, 136, - 137, 120, 120, 120, 120, 120, 137, 120, 120, 137, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 115, 139, 139, 118, 126, 126, 140, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 118, 126, 120, 120, - 120, 120, 120, 120, 120, 112, 119, 120, 120, 120, 120, 137, 120, 141, - 141, 120, 120, 119, 137, 120, 120, 137, 126, 126, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 126, 126, 126, 143, 143, 126, 144, 144, - 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 64, 145, 146, - 147, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, - 146, 148, 149, 148, 148, 149, 148, 148, 149, 149, 149, 148, 149, 149, - 148, 149, 148, 148, 148, 149, 148, 149, 148, 149, 148, 149, 148, 148, 64, - 64, 146, 146, 146, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 150, 64, 64, 64, 64, 64, 64, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 154, 154, 154, 154, 154, 154, 154, 155, 154, 156, - 156, 157, 158, 158, 158, 156, 64, 64, 64, 64, 64, 159, 159, 159, 159, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 160, 160, 160, 160, - 161, 160, 160, 160, 160, 160, 160, 160, 160, 160, 161, 160, 160, 160, - 161, 160, 160, 160, 160, 160, 64, 64, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 64, 163, 163, 163, 163, 163, 163, - 163, 163, 163, 164, 164, 164, 64, 64, 165, 64, 126, 126, 126, 126, 126, - 64, 64, 64, 64, 64, 64, 137, 120, 120, 137, 120, 120, 137, 120, 120, 120, - 137, 137, 137, 166, 167, 168, 120, 120, 120, 137, 120, 120, 137, 137, - 120, 120, 120, 120, 120, 169, 169, 169, 170, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 169, 170, 172, 171, 170, - 170, 170, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, - 173, 170, 170, 171, 78, 136, 174, 174, 169, 169, 169, 171, 171, 169, 169, - 84, 84, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 177, 171, - 171, 171, 171, 171, 171, 178, 179, 180, 180, 64, 178, 178, 178, 178, 178, - 178, 178, 178, 64, 64, 178, 178, 64, 64, 178, 178, 178, 178, 178, 178, - 178, 178, 178, 178, 178, 178, 178, 178, 64, 178, 178, 178, 178, 178, 178, - 178, 64, 178, 64, 64, 64, 178, 178, 178, 178, 64, 64, 181, 178, 180, 180, - 180, 179, 179, 179, 179, 64, 64, 180, 180, 64, 64, 180, 180, 182, 178, - 64, 64, 64, 64, 64, 64, 64, 64, 180, 64, 64, 64, 64, 178, 178, 64, 178, - 178, 178, 179, 179, 64, 64, 183, 183, 183, 183, 183, 183, 183, 183, 183, - 183, 178, 178, 184, 184, 185, 185, 185, 185, 185, 185, 186, 184, 64, 64, - 64, 64, 64, 187, 187, 188, 64, 189, 189, 189, 189, 189, 189, 64, 64, 64, - 64, 189, 189, 64, 64, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 64, 189, 189, 189, 189, 189, 189, 189, 64, 189, 189, - 64, 189, 189, 64, 189, 189, 64, 64, 190, 64, 188, 188, 188, 187, 187, 64, - 64, 64, 64, 187, 187, 64, 64, 187, 187, 191, 64, 64, 64, 187, 64, 64, 64, - 64, 64, 64, 64, 189, 189, 189, 189, 64, 189, 64, 64, 64, 64, 64, 64, 64, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 187, 187, 189, 189, - 189, 187, 64, 64, 64, 193, 193, 194, 64, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 64, 195, 195, 195, 64, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 64, 195, 195, 195, 195, 195, 195, 195, - 64, 195, 195, 64, 195, 195, 195, 195, 195, 64, 64, 196, 195, 194, 194, - 194, 193, 193, 193, 193, 193, 64, 193, 193, 194, 64, 194, 194, 197, 64, - 64, 195, 64, 64, 64, 64, 64, 64, 64, 195, 195, 193, 193, 64, 64, 198, - 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 200, 64, 64, 64, 64, - 64, 64, 64, 195, 64, 64, 64, 64, 64, 64, 64, 201, 202, 202, 64, 203, 203, - 203, 203, 203, 203, 203, 203, 64, 64, 203, 203, 64, 64, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 64, 203, 203, 203, - 203, 203, 203, 203, 64, 203, 203, 64, 203, 203, 203, 203, 203, 64, 64, - 204, 203, 202, 201, 202, 201, 201, 201, 201, 64, 64, 202, 202, 64, 64, - 202, 202, 205, 64, 64, 64, 64, 64, 64, 64, 64, 201, 202, 64, 64, 64, 64, - 203, 203, 64, 203, 203, 203, 201, 201, 64, 64, 206, 206, 206, 206, 206, - 206, 206, 206, 206, 206, 207, 203, 208, 208, 208, 208, 208, 208, 64, 64, - 209, 210, 64, 210, 210, 210, 210, 210, 210, 64, 64, 64, 210, 210, 210, - 64, 210, 210, 210, 210, 64, 64, 64, 210, 210, 64, 210, 64, 210, 210, 64, - 64, 64, 210, 210, 64, 64, 64, 210, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 64, 64, 64, 64, 211, 211, 209, 211, 211, 64, 64, 64, 211, 211, - 211, 64, 211, 211, 211, 212, 64, 64, 210, 64, 64, 64, 64, 64, 64, 211, - 64, 64, 64, 64, 64, 64, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, - 214, 214, 214, 215, 215, 215, 215, 215, 215, 216, 215, 64, 64, 64, 64, - 64, 217, 218, 218, 218, 64, 219, 219, 219, 219, 219, 219, 219, 219, 64, - 219, 219, 219, 64, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 64, 64, 64, 219, 217, 217, 217, 218, 218, 218, - 218, 64, 217, 217, 217, 64, 217, 217, 217, 220, 64, 64, 64, 64, 64, 64, - 64, 221, 222, 64, 219, 219, 219, 64, 64, 64, 64, 64, 219, 219, 217, 217, - 64, 64, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, 224, - 224, 224, 224, 224, 225, 64, 226, 227, 227, 64, 228, 228, 228, 228, 228, - 228, 228, 228, 64, 228, 228, 228, 64, 228, 228, 228, 228, 228, 228, 228, - 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 64, 228, 228, 228, - 228, 228, 64, 64, 229, 228, 227, 230, 227, 227, 227, 227, 227, 64, 230, - 227, 227, 64, 227, 227, 226, 231, 64, 64, 64, 64, 64, 64, 64, 227, 227, - 64, 64, 64, 64, 64, 64, 64, 228, 64, 228, 228, 226, 226, 64, 64, 232, - 232, 232, 232, 232, 232, 232, 232, 232, 232, 64, 228, 228, 64, 64, 64, - 64, 64, 64, 233, 234, 234, 64, 235, 235, 235, 235, 235, 235, 235, 235, - 64, 235, 235, 235, 64, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, - 235, 235, 235, 235, 235, 235, 235, 64, 64, 235, 234, 234, 234, 233, 233, - 233, 233, 64, 234, 234, 234, 64, 234, 234, 234, 236, 235, 64, 64, 64, 64, - 64, 64, 64, 64, 234, 64, 64, 64, 64, 64, 64, 64, 235, 235, 235, 233, 233, - 64, 64, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, - 238, 238, 238, 64, 64, 64, 239, 235, 235, 235, 235, 235, 235, 64, 64, - 240, 240, 64, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 241, 241, 64, 64, 64, 241, 241, 241, 241, 241, 241, - 241, 241, 64, 241, 241, 241, 241, 241, 241, 241, 241, 241, 64, 241, 64, - 64, 64, 64, 242, 64, 64, 64, 64, 240, 240, 240, 243, 243, 243, 64, 243, - 64, 240, 240, 240, 240, 240, 240, 240, 240, 64, 64, 64, 64, 64, 64, 244, - 244, 244, 244, 244, 244, 244, 244, 244, 244, 64, 64, 240, 240, 245, 64, - 64, 64, 64, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 247, 246, 246, 247, 247, 247, 247, 248, 248, 249, 64, - 64, 64, 64, 250, 246, 246, 246, 246, 246, 246, 251, 247, 252, 252, 252, - 252, 247, 247, 247, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, - 254, 253, 253, 64, 64, 64, 64, 64, 255, 255, 64, 255, 64, 64, 255, 255, - 64, 255, 64, 64, 255, 64, 64, 64, 64, 64, 64, 255, 255, 255, 255, 64, - 255, 255, 255, 255, 255, 255, 255, 64, 255, 255, 255, 64, 255, 64, 255, - 64, 64, 255, 255, 64, 255, 255, 255, 255, 256, 255, 255, 256, 256, 256, - 256, 257, 257, 64, 256, 256, 255, 64, 64, 255, 255, 255, 255, 255, 64, - 258, 64, 259, 259, 259, 259, 256, 256, 64, 64, 260, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 64, 64, 255, 255, 255, 255, 261, 262, 262, 262, - 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, - 263, 262, 263, 262, 262, 262, 264, 264, 262, 262, 262, 262, 262, 262, - 265, 265, 265, 265, 265, 265, 265, 265, 265, 265, 266, 266, 266, 266, - 266, 266, 266, 266, 266, 266, 262, 264, 262, 264, 262, 267, 268, 269, - 268, 269, 270, 270, 261, 261, 261, 261, 261, 261, 261, 261, 64, 261, 261, - 261, 261, 261, 261, 261, 261, 261, 261, 261, 261, 64, 64, 64, 64, 271, - 272, 273, 274, 273, 273, 273, 273, 273, 272, 272, 272, 272, 273, 270, - 272, 273, 275, 275, 276, 263, 275, 275, 261, 261, 261, 261, 261, 273, - 273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 64, 273, 273, 273, 273, - 273, 273, 273, 273, 273, 273, 273, 273, 64, 262, 262, 262, 262, 262, 262, - 262, 262, 264, 262, 262, 262, 262, 262, 262, 64, 262, 262, 263, 263, 263, - 263, 263, 277, 277, 277, 277, 263, 263, 64, 64, 64, 64, 64, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 278, 278, 279, 279, 280, 280, 280, - 280, 279, 280, 280, 280, 280, 280, 281, 279, 282, 282, 279, 279, 280, - 280, 278, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284, 284, - 284, 284, 284, 284, 278, 278, 278, 278, 278, 278, 279, 279, 280, 280, - 278, 278, 278, 278, 280, 280, 280, 278, 279, 279, 279, 278, 278, 279, - 279, 279, 279, 279, 279, 279, 278, 278, 278, 280, 280, 280, 280, 278, - 278, 278, 278, 278, 280, 279, 279, 280, 280, 279, 279, 279, 279, 279, - 279, 285, 278, 279, 283, 283, 279, 279, 279, 280, 286, 286, 287, 287, - 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 287, 64, 287, 64, - 64, 64, 64, 64, 287, 64, 64, 288, 288, 288, 288, 288, 288, 288, 288, 288, - 288, 288, 84, 289, 288, 288, 288, 290, 290, 290, 290, 290, 290, 290, 290, - 291, 291, 291, 291, 291, 291, 291, 291, 292, 292, 292, 292, 292, 292, - 292, 292, 292, 64, 292, 292, 292, 292, 64, 64, 292, 292, 292, 292, 292, - 292, 292, 64, 292, 292, 292, 64, 64, 293, 293, 293, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, 64, 64, 64, 296, - 296, 296, 296, 296, 296, 296, 296, 296, 296, 64, 64, 64, 64, 64, 64, 297, - 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 297, 64, 64, - 298, 298, 298, 298, 298, 298, 64, 64, 299, 300, 300, 300, 300, 300, 300, - 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, - 301, 301, 300, 302, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 304, 305, 64, 64, 64, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 84, 84, 84, 307, 307, 307, - 306, 306, 306, 306, 306, 306, 306, 306, 64, 64, 64, 64, 64, 64, 64, 308, - 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 64, 308, 308, - 308, 308, 309, 309, 310, 64, 64, 64, 311, 311, 311, 311, 311, 311, 311, - 311, 311, 311, 312, 312, 313, 84, 84, 64, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 315, 315, 64, 64, 64, 64, 316, 316, 316, 316, 316, - 316, 316, 316, 316, 316, 316, 316, 316, 64, 316, 316, 316, 64, 317, 317, - 64, 64, 64, 64, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - 318, 319, 319, 320, 319, 319, 319, 319, 319, 319, 319, 320, 320, 320, - 320, 320, 320, 320, 320, 319, 320, 320, 319, 319, 319, 319, 319, 319, - 319, 319, 319, 321, 319, 322, 322, 322, 323, 322, 322, 322, 324, 318, - 325, 64, 64, 326, 326, 326, 326, 326, 326, 326, 326, 326, 326, 64, 64, - 64, 64, 64, 64, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 64, 64, - 64, 64, 64, 64, 328, 328, 66, 66, 328, 66, 329, 328, 328, 328, 328, 330, - 330, 330, 331, 64, 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, 64, - 64, 64, 64, 64, 64, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, - 333, 334, 333, 333, 333, 333, 333, 335, 333, 64, 64, 64, 64, 64, 300, - 300, 300, 300, 300, 300, 64, 64, 336, 336, 336, 336, 336, 336, 336, 336, - 336, 336, 336, 336, 336, 336, 336, 64, 337, 337, 337, 338, 338, 338, 338, - 337, 337, 338, 338, 338, 64, 64, 64, 64, 338, 338, 337, 338, 338, 338, - 338, 338, 338, 339, 340, 341, 64, 64, 64, 64, 342, 64, 64, 64, 343, 343, - 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 345, 345, 345, 345, - 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 64, 64, 345, 345, 345, - 345, 345, 64, 64, 64, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 64, 64, 64, 64, 346, 346, 64, 64, 64, 64, 64, 64, 347, 347, - 347, 347, 347, 347, 347, 347, 347, 347, 348, 64, 64, 64, 349, 349, 350, - 350, 350, 350, 350, 350, 350, 350, 351, 351, 351, 351, 351, 351, 351, - 351, 351, 351, 351, 351, 351, 351, 351, 352, 353, 354, 354, 355, 64, 64, - 356, 356, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, 357, - 357, 358, 359, 358, 359, 359, 359, 359, 359, 359, 359, 64, 360, 358, 359, - 358, 358, 359, 359, 359, 359, 359, 359, 359, 359, 358, 358, 358, 358, - 358, 358, 359, 359, 361, 361, 361, 361, 361, 361, 361, 361, 64, 64, 362, - 363, 363, 363, 363, 363, 363, 363, 363, 363, 363, 64, 64, 64, 64, 64, 64, - 364, 364, 364, 364, 364, 364, 364, 365, 364, 364, 364, 364, 364, 364, 64, - 64, 78, 78, 78, 78, 78, 136, 136, 136, 136, 136, 136, 78, 78, 136, 366, - 64, 367, 367, 367, 367, 368, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 370, 368, 367, 367, 367, 367, 367, 368, - 367, 368, 368, 368, 368, 368, 367, 368, 371, 369, 369, 369, 369, 369, - 369, 369, 64, 64, 64, 64, 372, 372, 372, 372, 372, 372, 372, 372, 372, - 372, 373, 373, 373, 373, 373, 373, 373, 374, 374, 374, 374, 374, 374, - 374, 374, 374, 374, 375, 376, 375, 375, 375, 375, 375, 375, 375, 374, - 374, 374, 374, 374, 374, 374, 374, 374, 64, 64, 64, 377, 377, 378, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 378, - 377, 377, 377, 377, 378, 378, 377, 377, 380, 381, 377, 377, 379, 379, - 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 379, 379, 379, 379, - 379, 379, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, - 383, 383, 384, 385, 386, 386, 385, 385, 385, 386, 385, 386, 386, 386, - 387, 387, 64, 64, 64, 64, 64, 64, 64, 64, 388, 388, 388, 388, 389, 389, - 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 390, 390, 390, 390, - 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391, 390, 390, - 391, 392, 64, 64, 64, 393, 393, 393, 393, 393, 394, 394, 394, 394, 394, - 394, 394, 394, 394, 394, 64, 64, 64, 389, 389, 389, 395, 395, 395, 395, - 395, 395, 395, 395, 395, 395, 396, 396, 396, 396, 396, 396, 396, 396, - 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397, 398, 398, - 399, 399, 399, 399, 399, 399, 399, 399, 78, 78, 78, 84, 400, 136, 136, - 136, 136, 136, 78, 78, 136, 136, 136, 136, 78, 401, 400, 400, 400, 400, - 400, 400, 400, 402, 402, 402, 402, 136, 402, 402, 402, 402, 401, 401, 78, - 402, 402, 64, 78, 78, 64, 64, 64, 64, 64, 64, 41, 41, 41, 41, 41, 41, 62, - 62, 62, 62, 62, 75, 44, 44, 44, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, - 65, 44, 44, 44, 44, 65, 65, 65, 65, 65, 41, 41, 41, 41, 41, 403, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, - 44, 44, 65, 78, 78, 136, 78, 78, 78, 78, 78, 78, 78, 136, 78, 78, 404, - 405, 136, 406, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 78, 78, 64, 64, 64, 64, 64, 64, 407, 136, 78, 136, - 37, 41, 37, 41, 37, 41, 41, 41, 41, 41, 41, 41, 41, 41, 37, 41, 62, 62, - 62, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, - 62, 62, 64, 64, 61, 61, 61, 61, 61, 61, 64, 64, 64, 61, 64, 61, 64, 61, - 64, 61, 408, 408, 408, 408, 408, 408, 408, 408, 62, 62, 62, 62, 62, 64, - 62, 62, 61, 61, 61, 61, 408, 63, 62, 63, 63, 63, 62, 62, 62, 64, 62, 62, - 61, 61, 61, 61, 408, 63, 63, 63, 62, 62, 62, 62, 64, 64, 62, 62, 61, 61, - 61, 61, 64, 63, 63, 63, 61, 61, 61, 61, 61, 63, 63, 63, 64, 64, 62, 62, - 62, 64, 62, 62, 61, 61, 61, 61, 408, 63, 63, 64, 409, 409, 409, 409, 409, - 409, 409, 409, 409, 409, 409, 410, 411, 411, 412, 413, 414, 415, 415, - 414, 414, 414, 22, 66, 416, 417, 418, 419, 416, 417, 418, 419, 22, 22, - 22, 66, 22, 22, 22, 22, 420, 421, 422, 423, 424, 425, 426, 21, 427, 428, - 427, 427, 428, 22, 66, 66, 66, 28, 35, 22, 66, 66, 22, 429, 429, 66, 66, - 66, 430, 431, 432, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 433, 66, - 429, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 409, 410, 410, 410, 410, - 410, 64, 434, 435, 436, 437, 410, 410, 410, 410, 410, 410, 438, 44, 64, - 64, 33, 438, 438, 438, 438, 438, 439, 439, 433, 431, 432, 440, 438, 33, - 33, 33, 33, 438, 438, 438, 438, 438, 439, 439, 433, 431, 432, 64, 44, 44, - 44, 44, 44, 64, 64, 64, 250, 250, 250, 250, 250, 250, 250, 250, 250, 441, - 250, 250, 23, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 64, 78, - 78, 400, 400, 78, 78, 78, 78, 400, 400, 400, 78, 78, 366, 366, 366, 366, - 78, 366, 366, 366, 400, 400, 78, 136, 78, 400, 400, 136, 136, 136, 136, - 78, 64, 64, 64, 64, 64, 64, 64, 26, 26, 442, 30, 26, 30, 26, 442, 26, 30, - 34, 442, 442, 442, 34, 34, 442, 442, 442, 443, 26, 442, 30, 26, 433, 442, - 442, 442, 442, 442, 26, 26, 26, 30, 30, 26, 442, 26, 67, 26, 442, 26, 37, - 38, 442, 442, 444, 34, 442, 442, 37, 442, 34, 402, 402, 402, 402, 34, 26, - 26, 34, 34, 442, 442, 445, 433, 433, 433, 433, 442, 34, 34, 34, 34, 26, - 433, 26, 26, 41, 277, 446, 446, 446, 36, 36, 446, 446, 446, 446, 446, - 446, 36, 36, 36, 36, 446, 447, 447, 447, 447, 447, 447, 447, 447, 447, - 447, 447, 447, 448, 448, 448, 448, 447, 447, 448, 448, 448, 448, 448, - 448, 448, 448, 448, 37, 41, 448, 448, 448, 448, 36, 26, 26, 64, 64, 64, - 64, 39, 39, 39, 39, 39, 30, 30, 30, 30, 30, 433, 433, 26, 26, 26, 26, - 433, 26, 26, 433, 26, 26, 433, 26, 26, 26, 26, 26, 26, 26, 433, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 30, 30, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 433, 433, 26, 26, 39, 26, 39, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 30, 26, 26, 26, 26, 433, 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 39, 445, 449, 449, 445, 433, 433, 39, 449, 445, 445, 449, - 445, 445, 433, 39, 433, 449, 439, 450, 433, 449, 445, 433, 433, 433, 449, - 445, 445, 449, 39, 449, 449, 445, 445, 39, 445, 39, 445, 39, 39, 39, 39, - 449, 449, 445, 449, 445, 445, 445, 445, 445, 39, 39, 39, 39, 433, 445, - 433, 445, 449, 449, 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, - 449, 445, 445, 445, 449, 433, 433, 433, 433, 433, 449, 445, 445, 445, - 433, 433, 433, 433, 433, 433, 433, 433, 433, 445, 449, 39, 445, 433, 449, - 449, 449, 449, 445, 445, 449, 449, 433, 433, 449, 449, 445, 445, 449, - 449, 445, 445, 449, 449, 445, 445, 445, 445, 445, 433, 433, 445, 445, - 445, 445, 433, 433, 39, 433, 433, 445, 39, 433, 433, 433, 433, 433, 433, - 433, 433, 445, 445, 433, 39, 445, 445, 445, 433, 433, 433, 433, 433, 445, - 449, 433, 445, 445, 445, 445, 445, 433, 433, 445, 445, 433, 433, 433, - 433, 445, 445, 445, 445, 445, 445, 445, 445, 433, 433, 431, 432, 431, - 432, 26, 26, 26, 26, 26, 26, 30, 26, 26, 26, 26, 26, 445, 445, 26, 26, - 26, 26, 26, 26, 26, 451, 452, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 26, 433, - 26, 26, 26, 26, 26, 26, 26, 26, 277, 26, 26, 26, 26, 26, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 26, 26, 26, 26, 433, 433, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 64, 64, 64, 64, 64, 26, 26, 26, 26, 26, 26, 26, 64, - 36, 36, 36, 36, 36, 36, 36, 36, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, 453, - 453, 446, 36, 36, 36, 36, 36, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 26, 26, 26, 26, 26, 26, 30, 30, 30, 30, 26, 26, 30, 30, 26, 30, 30, - 30, 30, 30, 26, 26, 30, 30, 26, 26, 30, 39, 26, 26, 26, 26, 30, 30, 26, - 26, 30, 39, 26, 26, 26, 26, 30, 30, 30, 26, 26, 30, 26, 26, 30, 30, 26, - 26, 26, 26, 26, 30, 30, 26, 26, 30, 26, 26, 26, 26, 30, 30, 26, 26, 26, - 26, 30, 26, 30, 26, 30, 26, 30, 26, 26, 26, 26, 26, 30, 30, 26, 30, 30, - 30, 26, 30, 30, 30, 30, 26, 30, 30, 26, 39, 26, 26, 26, 26, 26, 26, 30, - 30, 26, 26, 26, 26, 277, 26, 26, 26, 26, 26, 26, 26, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 26, 30, 30, 30, 26, 30, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 30, 26, 26, 431, 432, 431, 432, 431, 432, 431, 432, 431, 432, - 431, 432, 431, 432, 36, 36, 446, 446, 446, 446, 446, 446, 446, 446, 446, - 446, 446, 446, 26, 26, 26, 26, 445, 433, 433, 445, 445, 431, 432, 433, - 445, 445, 433, 445, 445, 445, 433, 433, 433, 433, 433, 445, 445, 445, - 445, 433, 433, 433, 433, 433, 445, 445, 445, 433, 433, 433, 445, 445, - 445, 445, 9, 10, 9, 10, 9, 10, 9, 10, 431, 432, 454, 454, 454, 454, 454, - 454, 454, 454, 433, 433, 433, 431, 432, 9, 10, 431, 432, 431, 432, 431, - 432, 431, 432, 431, 432, 433, 433, 445, 445, 445, 445, 445, 445, 433, - 433, 433, 433, 433, 433, 433, 433, 445, 433, 433, 433, 433, 445, 445, - 445, 445, 445, 433, 445, 445, 433, 433, 431, 432, 431, 432, 445, 433, - 433, 433, 433, 445, 433, 445, 445, 445, 433, 433, 445, 445, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, 445, 445, 445, 445, 445, 445, - 433, 433, 431, 432, 433, 433, 433, 433, 445, 445, 445, 445, 445, 445, - 445, 445, 445, 445, 445, 433, 445, 445, 445, 445, 433, 433, 445, 433, - 445, 433, 433, 445, 433, 445, 445, 445, 445, 433, 433, 433, 433, 433, - 445, 445, 433, 433, 433, 433, 445, 445, 445, 445, 433, 445, 445, 433, - 433, 445, 445, 433, 433, 433, 433, 445, 445, 445, 445, 445, 445, 445, - 445, 445, 445, 445, 433, 433, 445, 445, 445, 445, 445, 445, 445, 445, - 433, 445, 445, 445, 445, 445, 445, 445, 445, 433, 433, 433, 433, 433, - 445, 433, 445, 433, 433, 433, 445, 445, 445, 445, 445, 433, 433, 433, - 433, 445, 433, 433, 433, 445, 445, 445, 445, 445, 433, 445, 433, 433, - 433, 433, 433, 433, 433, 26, 26, 433, 433, 433, 433, 433, 433, 26, 26, - 26, 26, 26, 26, 26, 26, 30, 30, 30, 26, 26, 26, 26, 64, 64, 26, 26, 26, - 26, 26, 26, 26, 26, 64, 64, 26, 26, 64, 64, 64, 26, 26, 26, 26, 64, 26, - 26, 26, 26, 26, 26, 26, 26, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 26, - 26, 26, 26, 455, 455, 455, 455, 455, 455, 455, 455, 455, 455, 455, 455, - 455, 455, 455, 64, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, - 456, 456, 456, 456, 64, 37, 41, 37, 37, 37, 41, 41, 37, 41, 37, 41, 37, - 41, 37, 37, 37, 37, 41, 37, 41, 41, 37, 41, 41, 41, 41, 41, 41, 44, 44, - 37, 37, 69, 70, 69, 70, 70, 457, 457, 457, 457, 457, 457, 69, 70, 69, 70, - 458, 458, 458, 69, 70, 64, 64, 64, 64, 64, 459, 459, 459, 459, 460, 459, - 459, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, - 461, 64, 461, 64, 64, 64, 64, 64, 461, 64, 64, 462, 462, 462, 462, 462, - 462, 462, 462, 64, 64, 64, 64, 64, 64, 64, 463, 464, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 465, 77, 77, 77, 77, 77, 77, 77, 77, - 66, 66, 28, 35, 28, 35, 66, 66, 66, 28, 35, 66, 28, 35, 66, 66, 66, 66, - 66, 66, 66, 66, 66, 415, 66, 66, 415, 66, 28, 35, 66, 66, 28, 35, 431, - 432, 431, 432, 431, 432, 431, 432, 66, 66, 66, 66, 66, 45, 66, 66, 415, - 415, 66, 66, 66, 66, 415, 66, 418, 64, 64, 64, 64, 64, 466, 466, 466, - 466, 466, 466, 466, 466, 466, 466, 64, 466, 466, 466, 466, 466, 466, 466, - 466, 466, 64, 64, 64, 64, 466, 466, 466, 466, 466, 466, 64, 64, 467, 467, - 467, 467, 467, 467, 467, 467, 467, 467, 467, 467, 64, 64, 64, 64, 468, - 469, 469, 469, 467, 470, 471, 472, 451, 452, 451, 452, 451, 452, 451, - 452, 451, 452, 467, 467, 451, 452, 451, 452, 451, 452, 451, 452, 473, - 474, 475, 475, 467, 472, 472, 472, 472, 472, 472, 472, 472, 472, 476, - 477, 478, 479, 480, 480, 473, 481, 481, 481, 481, 481, 467, 467, 472, - 472, 472, 470, 471, 469, 467, 26, 64, 482, 482, 482, 482, 482, 482, 482, - 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, - 482, 64, 64, 483, 483, 484, 484, 485, 485, 482, 473, 486, 486, 486, 486, - 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, - 469, 481, 487, 487, 486, 64, 64, 64, 64, 64, 488, 488, 488, 488, 488, - 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 64, 64, 64, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 64, - 489, 489, 490, 490, 490, 490, 489, 489, 489, 489, 489, 489, 489, 489, - 489, 489, 488, 488, 488, 64, 64, 64, 64, 64, 491, 491, 491, 491, 491, - 491, 491, 491, 491, 491, 491, 491, 491, 492, 492, 64, 490, 490, 490, 490, - 490, 490, 490, 490, 490, 490, 489, 489, 489, 489, 489, 489, 493, 493, - 493, 493, 493, 493, 493, 493, 467, 494, 494, 494, 494, 494, 494, 494, - 494, 494, 494, 494, 494, 494, 494, 494, 491, 491, 491, 491, 492, 492, - 492, 489, 489, 494, 494, 494, 494, 494, 494, 494, 489, 489, 489, 489, - 467, 467, 467, 467, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495, 495, 495, 495, 495, 64, 489, 489, 489, 489, 489, 489, 489, 467, 467, - 467, 467, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 467, - 467, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, - 496, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 498, 498, 498, - 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 499, 498, 498, 498, - 498, 498, 498, 498, 64, 64, 64, 500, 500, 500, 500, 500, 500, 500, 500, - 500, 500, 500, 500, 500, 500, 500, 64, 501, 501, 501, 501, 501, 501, 501, - 501, 502, 502, 502, 502, 502, 502, 503, 503, 504, 504, 504, 504, 504, - 504, 504, 504, 504, 504, 504, 504, 505, 506, 506, 506, 507, 507, 507, - 507, 507, 507, 507, 507, 507, 507, 504, 504, 64, 64, 64, 64, 72, 75, 72, - 75, 72, 75, 508, 77, 79, 79, 79, 509, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 509, 510, 72, 75, 72, 75, 403, 403, 77, 77, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 512, 512, 512, 512, 512, - 512, 512, 512, 512, 512, 513, 513, 514, 514, 514, 514, 514, 514, 47, 47, - 47, 47, 47, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 37, 41, - 37, 41, 37, 41, 41, 41, 37, 41, 37, 41, 37, 41, 44, 41, 41, 41, 41, 41, - 41, 41, 41, 37, 41, 37, 41, 37, 37, 41, 45, 515, 515, 37, 41, 37, 41, 42, - 37, 41, 37, 41, 41, 41, 37, 41, 37, 41, 37, 37, 37, 37, 64, 64, 37, 37, - 37, 37, 37, 41, 37, 41, 64, 64, 64, 64, 64, 64, 64, 42, 44, 44, 41, 42, - 42, 42, 42, 42, 516, 516, 517, 516, 516, 516, 518, 516, 516, 516, 516, - 517, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, - 516, 516, 519, 519, 517, 517, 519, 520, 520, 520, 520, 64, 64, 64, 64, - 521, 521, 521, 521, 521, 521, 277, 277, 250, 444, 64, 64, 64, 64, 64, 64, - 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 523, 523, - 523, 523, 524, 524, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, - 525, 525, 525, 525, 525, 525, 525, 525, 524, 524, 524, 524, 524, 524, - 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, 526, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 527, 527, 528, 528, 528, 528, 528, 528, 528, 528, - 528, 528, 64, 64, 64, 64, 64, 64, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 171, 171, 171, 171, 171, 171, 176, 176, 176, 171, 176, 171, 64, - 64, 529, 529, 529, 529, 529, 529, 529, 529, 529, 529, 530, 530, 530, 530, - 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, - 530, 530, 531, 531, 531, 531, 531, 532, 532, 532, 84, 533, 534, 534, 534, - 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 535, 535, - 535, 535, 535, 535, 535, 535, 535, 535, 535, 536, 537, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 538, 290, 290, 290, 290, 290, 64, 64, 64, - 539, 539, 539, 540, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, - 541, 541, 541, 541, 541, 542, 540, 540, 539, 539, 539, 539, 540, 540, - 539, 540, 540, 540, 543, 544, 544, 544, 544, 544, 544, 544, 544, 544, - 544, 544, 544, 544, 64, 46, 545, 545, 545, 545, 545, 545, 545, 545, 545, - 545, 64, 64, 64, 64, 544, 544, 278, 278, 278, 278, 278, 280, 546, 278, - 283, 283, 278, 278, 278, 278, 278, 64, 547, 547, 547, 547, 547, 547, 547, - 547, 547, 548, 548, 548, 548, 548, 548, 549, 549, 548, 548, 549, 549, - 548, 548, 64, 547, 547, 547, 548, 547, 547, 547, 547, 547, 547, 547, 547, - 548, 549, 64, 64, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 64, - 64, 551, 551, 551, 551, 546, 278, 278, 278, 278, 278, 278, 286, 286, 286, - 278, 279, 280, 279, 278, 278, 552, 552, 552, 552, 552, 552, 552, 552, - 553, 552, 553, 553, 554, 552, 552, 553, 553, 552, 552, 552, 552, 552, - 553, 553, 552, 553, 552, 64, 64, 64, 64, 64, 64, 64, 64, 552, 552, 555, - 556, 556, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 558, - 559, 559, 558, 558, 560, 560, 557, 561, 561, 558, 562, 64, 64, 292, 292, - 292, 292, 292, 292, 64, 41, 41, 41, 515, 44, 44, 44, 44, 41, 41, 41, 41, - 41, 62, 64, 64, 298, 298, 298, 298, 298, 298, 298, 298, 557, 557, 557, - 558, 558, 559, 558, 558, 559, 558, 558, 560, 558, 562, 64, 64, 563, 563, - 563, 563, 563, 563, 563, 563, 563, 563, 64, 64, 64, 64, 64, 64, 290, 290, - 290, 290, 64, 64, 64, 64, 291, 291, 291, 291, 291, 291, 291, 64, 64, 64, - 64, 291, 291, 291, 291, 291, 291, 291, 291, 291, 64, 64, 64, 64, 564, - 564, 564, 564, 564, 564, 564, 564, 565, 565, 565, 565, 565, 565, 565, - 565, 496, 496, 497, 497, 497, 497, 497, 497, 41, 41, 41, 41, 41, 41, 41, - 64, 64, 64, 64, 83, 83, 83, 83, 83, 64, 64, 64, 64, 64, 110, 566, 110, - 110, 567, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 64, 110, 110, 110, 110, 110, 64, 110, 64, 110, 110, 64, 110, 110, - 64, 110, 110, 126, 126, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, - 568, 568, 568, 568, 568, 568, 64, 64, 64, 64, 64, 64, 64, 64, 64, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 569, 418, 64, 64, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 116, 119, 64, 64, 58, 58, - 58, 58, 58, 58, 58, 58, 469, 469, 469, 469, 469, 469, 469, 474, 475, 469, - 64, 64, 64, 64, 64, 64, 78, 78, 78, 78, 78, 78, 78, 136, 136, 136, 136, - 136, 136, 136, 77, 77, 469, 473, 473, 570, 570, 474, 475, 474, 475, 474, - 475, 474, 475, 474, 475, 474, 475, 474, 475, 474, 475, 469, 469, 474, - 475, 469, 469, 469, 469, 570, 570, 570, 571, 469, 571, 64, 469, 571, 469, - 469, 473, 451, 452, 451, 452, 451, 452, 572, 469, 469, 573, 574, 575, - 575, 576, 64, 469, 577, 572, 469, 64, 64, 64, 64, 126, 126, 126, 126, - 126, 64, 126, 126, 126, 126, 126, 126, 126, 64, 64, 410, 64, 578, 578, - 579, 580, 579, 578, 578, 581, 582, 578, 583, 584, 585, 584, 584, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 584, 578, 587, 588, 587, - 578, 578, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, - 589, 589, 589, 589, 589, 589, 581, 578, 582, 590, 591, 590, 592, 592, - 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, - 592, 592, 581, 588, 582, 588, 581, 582, 593, 594, 595, 593, 593, 596, - 596, 596, 596, 596, 596, 596, 596, 596, 596, 597, 596, 596, 596, 596, - 596, 596, 596, 596, 596, 596, 596, 596, 596, 597, 597, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 64, 64, 64, - 598, 598, 598, 598, 598, 598, 64, 64, 598, 598, 598, 64, 64, 64, 580, - 580, 588, 590, 599, 580, 580, 64, 600, 601, 601, 601, 601, 600, 600, 64, - 64, 602, 602, 602, 26, 30, 64, 64, 603, 603, 603, 603, 603, 603, 603, - 603, 603, 603, 603, 603, 64, 603, 603, 603, 603, 603, 603, 603, 603, 603, - 603, 64, 603, 603, 603, 64, 603, 603, 64, 603, 603, 603, 603, 603, 603, - 603, 64, 64, 603, 603, 603, 64, 64, 64, 64, 64, 84, 66, 84, 64, 64, 64, - 64, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 64, - 64, 64, 277, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, - 604, 605, 605, 605, 605, 606, 606, 606, 606, 606, 606, 606, 606, 606, - 606, 606, 606, 606, 606, 606, 606, 606, 605, 605, 606, 64, 64, 64, 26, - 26, 26, 26, 64, 64, 64, 64, 606, 64, 64, 64, 64, 64, 64, 64, 277, 277, - 277, 277, 277, 136, 64, 64, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 64, 64, 64, 608, 608, 608, 608, 608, 608, 608, 608, - 608, 64, 64, 64, 64, 64, 64, 64, 136, 438, 438, 438, 438, 438, 438, 438, - 438, 438, 438, 438, 438, 438, 438, 438, 438, 438, 438, 438, 64, 64, 64, - 64, 609, 609, 609, 609, 609, 609, 609, 609, 610, 610, 610, 610, 64, 64, - 64, 64, 611, 611, 611, 611, 611, 611, 611, 611, 611, 612, 611, 611, 611, - 611, 611, 611, 611, 611, 612, 64, 64, 64, 64, 64, 613, 613, 613, 613, - 613, 613, 613, 613, 613, 613, 613, 613, 613, 613, 614, 614, 614, 614, - 614, 64, 64, 64, 64, 64, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 64, 616, 617, 617, 617, 617, 617, 617, 617, 617, - 617, 617, 617, 617, 64, 64, 64, 64, 618, 619, 619, 619, 619, 619, 64, 64, - 620, 620, 620, 620, 620, 620, 620, 620, 621, 621, 621, 621, 621, 621, - 621, 621, 622, 622, 622, 622, 622, 622, 622, 622, 623, 623, 623, 623, - 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 64, 64, 624, 624, 624, - 624, 624, 624, 624, 624, 624, 624, 64, 64, 64, 64, 64, 64, 625, 625, 625, - 625, 625, 625, 625, 625, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 627, 628, 628, - 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 64, 628, - 628, 628, 628, 628, 628, 64, 64, 629, 629, 629, 629, 629, 629, 64, 64, - 629, 64, 629, 629, 629, 629, 629, 629, 629, 629, 629, 629, 629, 629, 629, - 629, 629, 629, 629, 629, 629, 629, 64, 629, 629, 64, 64, 64, 629, 64, 64, - 629, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, - 630, 64, 631, 632, 632, 632, 632, 632, 632, 632, 632, 633, 633, 633, 633, - 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 634, 634, 635, - 635, 635, 635, 635, 635, 635, 636, 636, 636, 636, 636, 636, 636, 636, - 636, 636, 636, 636, 636, 636, 636, 64, 64, 64, 64, 64, 64, 64, 64, 637, - 637, 637, 637, 637, 637, 637, 637, 637, 638, 638, 638, 638, 638, 638, - 638, 638, 638, 638, 638, 64, 638, 638, 64, 64, 64, 64, 64, 639, 639, 639, - 639, 639, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, - 640, 640, 641, 641, 641, 641, 641, 641, 64, 64, 64, 642, 643, 643, 643, - 643, 643, 643, 643, 643, 643, 643, 64, 64, 64, 64, 64, 644, 645, 645, - 645, 645, 645, 645, 645, 645, 646, 646, 646, 646, 646, 646, 646, 646, 64, - 64, 64, 64, 647, 647, 646, 646, 647, 647, 647, 647, 647, 647, 647, 647, - 64, 64, 647, 647, 647, 647, 647, 647, 648, 649, 649, 649, 64, 649, 649, - 64, 64, 64, 64, 64, 649, 650, 649, 651, 648, 648, 648, 648, 64, 648, 648, - 648, 64, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 64, 64, 64, 64, 651, 652, 650, 64, 64, 64, - 64, 653, 654, 654, 654, 654, 654, 654, 654, 654, 655, 655, 655, 655, 655, - 655, 655, 655, 655, 64, 64, 64, 64, 64, 64, 64, 656, 656, 656, 656, 656, - 656, 656, 656, 656, 656, 656, 656, 656, 657, 657, 658, 659, 659, 659, - 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 660, 660, 660, 661, - 661, 661, 661, 661, 661, 661, 661, 662, 661, 661, 661, 661, 661, 661, - 661, 661, 661, 661, 661, 661, 663, 664, 64, 64, 64, 64, 665, 665, 665, - 665, 665, 666, 666, 666, 666, 666, 666, 666, 64, 667, 667, 667, 667, 667, - 667, 667, 667, 667, 667, 667, 667, 667, 667, 64, 64, 64, 668, 668, 668, - 668, 668, 668, 668, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, - 669, 669, 669, 669, 64, 64, 670, 670, 670, 670, 670, 670, 670, 670, 671, - 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 64, 64, 64, 64, 64, - 672, 672, 672, 672, 672, 672, 672, 672, 673, 673, 673, 673, 673, 673, - 673, 673, 673, 673, 64, 64, 64, 64, 64, 64, 64, 674, 674, 674, 674, 64, - 64, 64, 64, 675, 675, 675, 675, 675, 675, 675, 676, 676, 676, 676, 676, - 676, 676, 676, 676, 64, 64, 64, 64, 64, 64, 64, 677, 677, 677, 677, 677, - 677, 677, 677, 677, 677, 677, 64, 64, 64, 64, 64, 678, 678, 678, 678, - 678, 678, 678, 678, 678, 678, 678, 64, 64, 64, 64, 64, 64, 64, 679, 679, - 679, 679, 679, 679, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, - 680, 680, 680, 680, 680, 64, 681, 682, 681, 683, 683, 683, 683, 683, 683, - 683, 683, 683, 683, 683, 683, 683, 682, 682, 682, 682, 682, 682, 682, - 682, 682, 682, 682, 682, 682, 682, 684, 685, 685, 685, 685, 685, 685, - 685, 64, 64, 64, 64, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, - 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 687, 687, 687, 687, - 687, 687, 687, 687, 687, 687, 64, 64, 64, 64, 64, 64, 64, 684, 688, 688, - 689, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, - 689, 689, 689, 688, 688, 688, 688, 689, 689, 691, 692, 693, 693, 694, - 693, 693, 693, 693, 64, 64, 64, 64, 64, 64, 695, 695, 695, 695, 695, 695, - 695, 695, 695, 64, 64, 64, 64, 64, 64, 64, 696, 696, 696, 696, 696, 696, - 696, 696, 696, 696, 64, 64, 64, 64, 64, 64, 697, 697, 697, 698, 698, 698, - 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, - 698, 698, 698, 699, 699, 699, 699, 699, 700, 699, 699, 699, 699, 699, - 699, 701, 701, 64, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 703, - 703, 703, 703, 64, 64, 64, 64, 704, 704, 704, 704, 704, 704, 704, 704, - 704, 704, 704, 705, 706, 706, 704, 64, 707, 707, 708, 709, 709, 709, 709, - 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 708, 708, - 708, 707, 707, 707, 707, 707, 707, 707, 707, 707, 708, 710, 709, 709, - 709, 709, 711, 711, 711, 711, 711, 712, 707, 707, 711, 64, 64, 713, 713, - 713, 713, 713, 713, 713, 713, 713, 713, 709, 711, 709, 711, 711, 711, 64, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 7, 7, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 11, 16, 17, 15, 18, 19, 20, 19, 21, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 19, 23, 24, 25, 24, 10, 15, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 27, 17, + 28, 29, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 16, 31, 32, 25, 1, 1, 1, 1, 1, 1, 33, 1, 1, 34, 35, 36, 13, + 37, 13, 38, 39, 40, 41, 42, 43, 25, 44, 45, 28, 46, 47, 48, 48, 49, 50, + 39, 39, 40, 48, 42, 51, 52, 52, 52, 35, 53, 53, 53, 53, 53, 53, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 53, 53, 53, 53, 53, 55, 54, 53, + 53, 53, 53, 53, 54, 56, 56, 56, 57, 57, 57, 57, 56, 57, 56, 56, 56, 57, + 56, 56, 57, 57, 56, 57, 56, 56, 57, 57, 57, 55, 56, 56, 56, 57, 56, 57, + 56, 57, 53, 56, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, + 53, 56, 53, 56, 53, 57, 53, 57, 53, 57, 53, 56, 53, 57, 53, 57, 53, 57, + 53, 57, 53, 57, 54, 56, 53, 56, 54, 56, 53, 57, 53, 57, 56, 53, 57, 53, + 57, 53, 57, 54, 56, 54, 56, 53, 56, 53, 57, 53, 56, 56, 54, 56, 53, 56, + 53, 57, 53, 57, 54, 56, 53, 57, 53, 57, 53, 53, 57, 53, 57, 53, 57, 57, + 57, 53, 53, 57, 53, 57, 53, 53, 57, 53, 53, 53, 57, 57, 53, 53, 53, 53, + 57, 53, 53, 57, 53, 53, 53, 57, 57, 57, 53, 53, 57, 53, 53, 57, 53, 57, + 53, 57, 53, 53, 57, 53, 57, 57, 53, 57, 53, 53, 57, 53, 53, 53, 57, 53, + 57, 53, 53, 57, 57, 58, 53, 57, 57, 57, 58, 58, 58, 58, 53, 59, 57, 53, + 59, 57, 53, 59, 57, 53, 56, 53, 56, 53, 56, 53, 56, 53, 56, 53, 56, 53, + 56, 53, 56, 57, 53, 57, 57, 53, 59, 57, 53, 57, 53, 53, 53, 57, 53, 57, + 57, 57, 57, 57, 57, 57, 53, 53, 57, 53, 53, 57, 57, 53, 57, 53, 53, 53, + 53, 57, 57, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 58, 57, 57, 57, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, + 61, 62, 62, 62, 62, 62, 62, 62, 63, 63, 64, 63, 61, 65, 66, 65, 65, 65, + 66, 65, 61, 61, 67, 62, 63, 63, 63, 63, 63, 63, 40, 40, 40, 40, 63, 40, + 63, 49, 60, 60, 60, 60, 60, 63, 63, 63, 63, 63, 68, 68, 61, 63, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 70, 71, 71, 71, 71, 70, 72, 71, 71, 71, 71, 71, 73, 73, 71, + 71, 71, 71, 73, 73, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 74, 74, + 74, 74, 74, 71, 71, 71, 71, 69, 69, 69, 69, 69, 69, 69, 69, 75, 69, 71, + 71, 71, 69, 69, 69, 71, 71, 76, 69, 69, 69, 71, 71, 71, 71, 69, 70, 71, + 71, 69, 77, 78, 78, 77, 78, 78, 77, 69, 69, 69, 69, 69, 79, 80, 79, 80, + 61, 81, 79, 80, 82, 82, 83, 80, 80, 80, 84, 79, 82, 82, 82, 82, 81, 63, + 79, 85, 79, 79, 79, 82, 79, 82, 79, 79, 80, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 82, 86, 86, 86, 86, 86, 86, 86, + 79, 79, 80, 80, 80, 80, 80, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 80, 87, 87, 87, 87, 87, 87, 87, 80, 80, 80, 80, + 80, 79, 80, 80, 79, 79, 79, 80, 80, 80, 79, 80, 79, 80, 79, 80, 79, 80, + 79, 80, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 80, 80, + 80, 80, 79, 80, 90, 79, 80, 79, 79, 80, 80, 79, 79, 79, 91, 92, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, + 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 94, 93, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 91, 94, 91, 94, 91, 94, 91, 94, 91, 94, + 95, 96, 96, 97, 97, 96, 98, 98, 91, 94, 91, 94, 91, 94, 91, 91, 94, 91, + 94, 91, 94, 91, 94, 91, 94, 91, 94, 91, 94, 94, 82, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 82, + 82, 100, 101, 101, 101, 101, 101, 101, 82, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 82, 103, 104, 82, 82, 105, + 105, 106, 82, 107, 108, 108, 108, 108, 107, 108, 108, 108, 109, 107, 108, + 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 108, 108, 107, + 108, 108, 109, 110, 108, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 120, 121, 122, 123, 124, 125, 126, 127, 128, 126, 108, 107, 129, + 119, 82, 82, 82, 82, 82, 82, 82, 82, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 82, 82, 82, 82, 82, 130, 130, 130, 126, 126, 82, 82, + 82, 131, 131, 131, 131, 131, 132, 133, 133, 134, 135, 135, 136, 137, 138, + 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 142, 143, 144, + 145, 82, 146, 144, 147, 147, 147, 147, 147, 147, 147, 147, 148, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 149, 150, 151, 152, 153, 154, + 155, 156, 97, 97, 157, 158, 140, 140, 140, 140, 140, 158, 140, 140, 158, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 135, 160, 160, 161, + 147, 147, 162, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 146, 147, 140, 140, 140, 140, 140, 140, 140, 132, 139, 140, 140, 140, + 140, 158, 140, 163, 163, 140, 140, 139, 158, 140, 140, 158, 147, 147, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 147, 147, 147, 165, + 165, 147, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 82, 167, 168, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 170, 171, 170, 170, 171, 170, 170, 171, 171, + 171, 170, 171, 171, 170, 171, 170, 170, 170, 171, 170, 171, 170, 171, + 170, 171, 170, 170, 82, 82, 168, 168, 168, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 172, 82, 82, 82, 82, 82, 82, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 176, + 176, 176, 177, 176, 178, 178, 179, 180, 181, 182, 178, 82, 82, 82, 82, + 82, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 184, 184, 184, 184, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 185, 184, 184, 184, 185, 184, 184, 184, 184, 184, 82, 82, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 82, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 188, 188, 188, 82, 82, 189, 82, 147, + 147, 147, 147, 147, 82, 147, 147, 147, 147, 147, 147, 147, 147, 82, 82, + 82, 82, 82, 82, 140, 140, 140, 140, 140, 140, 132, 158, 140, 140, 158, + 140, 140, 158, 140, 140, 140, 158, 158, 158, 190, 191, 192, 140, 140, + 140, 158, 140, 140, 158, 158, 140, 140, 140, 140, 140, 193, 193, 193, + 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 193, 194, 196, 195, 194, 194, 194, 193, 193, 193, 193, 193, 193, + 193, 193, 194, 194, 194, 194, 197, 194, 194, 195, 97, 157, 198, 198, 193, + 193, 193, 195, 195, 193, 193, 199, 199, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 201, 202, 195, 195, 195, 195, 195, 195, 203, 204, + 205, 205, 82, 203, 203, 203, 203, 203, 203, 203, 203, 82, 82, 203, 203, + 82, 82, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 82, 203, 203, 203, 203, 203, 203, 203, 82, 203, 82, 82, 82, 203, + 203, 203, 203, 82, 82, 206, 203, 205, 205, 205, 204, 204, 204, 204, 82, + 82, 205, 205, 82, 82, 205, 205, 207, 203, 82, 82, 82, 82, 82, 82, 82, 82, + 205, 82, 82, 82, 82, 203, 203, 82, 203, 203, 203, 204, 204, 82, 82, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 203, 203, 209, 209, 210, + 210, 210, 210, 210, 211, 212, 213, 82, 82, 82, 82, 82, 214, 214, 215, 82, + 216, 216, 216, 216, 216, 216, 82, 82, 82, 82, 216, 216, 82, 82, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 82, 216, 216, + 216, 216, 216, 216, 216, 82, 216, 216, 82, 216, 216, 82, 216, 216, 82, + 82, 217, 82, 215, 215, 215, 214, 214, 82, 82, 82, 82, 214, 214, 82, 82, + 214, 214, 218, 82, 82, 82, 214, 82, 82, 82, 82, 82, 82, 82, 216, 216, + 216, 216, 82, 216, 82, 82, 82, 82, 82, 82, 82, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 214, 214, 216, 216, 216, 214, 82, 82, 82, 220, + 220, 221, 82, 222, 222, 222, 222, 222, 222, 222, 222, 222, 82, 222, 222, + 222, 82, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 82, 222, 222, 222, 222, 222, 222, 222, 82, 222, 222, 82, 222, 222, + 222, 222, 222, 82, 82, 223, 222, 221, 221, 221, 220, 220, 220, 220, 220, + 82, 220, 220, 221, 82, 221, 221, 224, 82, 82, 222, 82, 82, 82, 82, 82, + 82, 82, 222, 222, 220, 220, 82, 82, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 226, 227, 82, 82, 82, 82, 82, 82, 82, 222, 82, 82, 82, 82, + 82, 82, 82, 228, 229, 229, 82, 230, 230, 230, 230, 230, 230, 230, 230, + 82, 82, 230, 230, 82, 82, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 82, 230, 230, 230, 230, 230, 230, 230, 82, 230, + 230, 82, 230, 230, 230, 230, 230, 82, 82, 231, 230, 229, 228, 229, 228, + 228, 228, 228, 82, 82, 229, 229, 82, 82, 229, 229, 232, 82, 82, 82, 82, + 82, 82, 82, 82, 228, 229, 82, 82, 82, 82, 230, 230, 82, 230, 230, 230, + 228, 228, 82, 82, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 234, + 230, 235, 235, 235, 235, 235, 235, 82, 82, 236, 237, 82, 237, 237, 237, + 237, 237, 237, 82, 82, 82, 237, 237, 237, 82, 237, 237, 237, 237, 82, 82, + 82, 237, 237, 82, 237, 82, 237, 237, 82, 82, 82, 237, 237, 82, 82, 82, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 82, 82, 82, 82, 238, + 238, 236, 238, 238, 82, 82, 82, 238, 238, 238, 82, 238, 238, 238, 239, + 82, 82, 237, 82, 82, 82, 82, 82, 82, 238, 82, 82, 82, 82, 82, 82, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, 241, 242, 242, + 242, 242, 242, 242, 243, 242, 82, 82, 82, 82, 82, 244, 245, 245, 245, 82, + 246, 246, 246, 246, 246, 246, 246, 246, 82, 246, 246, 246, 82, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 82, + 82, 82, 246, 244, 244, 244, 245, 245, 245, 245, 82, 244, 244, 244, 82, + 244, 244, 244, 247, 82, 82, 82, 82, 82, 82, 82, 248, 249, 82, 246, 246, + 246, 82, 82, 82, 82, 82, 246, 246, 244, 244, 82, 82, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 252, + 253, 254, 255, 255, 82, 253, 253, 253, 253, 253, 253, 253, 253, 82, 253, + 253, 253, 82, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 82, 253, 253, 253, 253, 253, 82, 82, 256, + 253, 255, 257, 255, 255, 255, 255, 255, 82, 257, 255, 255, 82, 255, 255, + 254, 258, 82, 82, 82, 82, 82, 82, 82, 255, 255, 82, 82, 82, 82, 82, 82, + 82, 253, 82, 253, 253, 254, 254, 82, 82, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 82, 253, 253, 82, 82, 82, 82, 82, 82, 260, 261, 261, + 82, 262, 262, 262, 262, 262, 262, 262, 262, 82, 262, 262, 262, 82, 262, + 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 82, 82, 262, 261, 261, 261, 260, 260, 260, 260, 82, 261, 261, + 261, 82, 261, 261, 261, 263, 262, 264, 82, 82, 82, 82, 262, 262, 262, + 261, 265, 265, 265, 265, 265, 265, 265, 262, 262, 262, 260, 260, 82, 82, + 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 265, 265, 265, 265, + 265, 265, 265, 265, 265, 267, 262, 262, 262, 262, 262, 262, 82, 82, 268, + 268, 82, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 269, 269, 269, 82, 82, 82, 269, 269, 269, 269, 269, 269, 269, + 269, 82, 269, 269, 269, 269, 269, 269, 269, 269, 269, 82, 269, 82, 82, + 82, 82, 270, 82, 82, 82, 82, 268, 268, 268, 271, 271, 271, 82, 271, 82, + 268, 268, 268, 268, 268, 268, 268, 268, 82, 82, 82, 82, 82, 82, 272, 272, + 272, 272, 272, 272, 272, 272, 272, 272, 82, 82, 268, 268, 273, 82, 82, + 82, 82, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 275, 274, 274, 275, 275, 275, 275, 276, 276, 277, 82, 82, + 82, 82, 278, 274, 274, 274, 274, 274, 274, 279, 275, 280, 280, 280, 280, + 275, 275, 275, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 82, 82, 82, 82, 82, 284, 284, 82, 284, 82, 82, 284, 284, 82, + 284, 82, 82, 284, 82, 82, 82, 82, 82, 82, 284, 284, 284, 284, 82, 284, + 284, 284, 284, 284, 284, 284, 82, 284, 284, 284, 82, 284, 82, 284, 82, + 82, 284, 284, 82, 284, 284, 284, 284, 285, 284, 284, 285, 285, 285, 285, + 286, 286, 82, 285, 285, 284, 82, 82, 284, 284, 284, 284, 284, 82, 287, + 82, 288, 288, 288, 288, 285, 285, 82, 82, 289, 289, 289, 289, 289, 289, + 289, 289, 289, 289, 82, 82, 284, 284, 284, 284, 290, 291, 291, 291, 292, + 293, 292, 292, 294, 292, 292, 295, 294, 296, 296, 296, 296, 296, 294, + 297, 296, 297, 297, 297, 298, 298, 297, 297, 297, 297, 297, 297, 299, + 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 301, 298, 297, 298, 297, 302, 303, 304, 303, + 304, 305, 305, 290, 290, 290, 290, 290, 290, 290, 290, 82, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 82, 82, 82, 82, 306, 307, + 308, 309, 308, 308, 308, 308, 308, 307, 307, 307, 307, 308, 310, 307, + 308, 311, 311, 312, 295, 311, 311, 290, 290, 290, 290, 290, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 308, 82, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 82, 301, 301, 297, 297, 297, 297, 297, + 297, 298, 297, 297, 297, 297, 297, 297, 82, 297, 297, 292, 292, 295, 292, + 293, 313, 313, 313, 313, 294, 294, 82, 82, 82, 82, 82, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 315, 315, 316, 316, 316, 316, + 315, 316, 316, 316, 316, 316, 317, 315, 318, 318, 315, 315, 316, 316, + 314, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 320, 320, 321, + 321, 321, 321, 314, 314, 314, 314, 314, 314, 315, 315, 316, 316, 314, + 314, 314, 314, 316, 316, 316, 314, 315, 315, 315, 314, 314, 315, 315, + 315, 315, 315, 315, 315, 314, 314, 314, 316, 316, 316, 316, 314, 314, + 314, 314, 314, 316, 315, 315, 316, 316, 315, 315, 315, 315, 315, 315, + 322, 314, 315, 319, 319, 315, 315, 315, 316, 323, 323, 324, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 82, 324, 82, 82, + 82, 82, 82, 324, 82, 82, 325, 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 326, 327, 325, 325, 325, 328, 328, 328, 328, 328, 328, 328, + 328, 329, 329, 329, 329, 329, 329, 329, 329, 330, 330, 330, 330, 330, + 330, 330, 330, 331, 331, 331, 331, 331, 331, 331, 331, 331, 82, 331, 331, + 331, 331, 82, 82, 331, 331, 331, 331, 331, 331, 331, 82, 331, 331, 331, + 82, 82, 332, 332, 332, 333, 334, 333, 333, 333, 333, 333, 333, 333, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 82, 82, 82, 336, 336, 336, 336, 336, 336, 336, + 336, 336, 336, 82, 82, 82, 82, 82, 82, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 82, 82, 338, 338, 338, 338, 338, 338, + 82, 82, 339, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 341, 341, 340, 342, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 344, 345, 82, 82, 82, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 199, 199, 199, 347, 347, 347, 346, 346, 346, 346, 346, + 346, 346, 346, 82, 82, 82, 82, 82, 82, 82, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 82, 348, 348, 348, 348, 349, 349, 350, + 82, 82, 82, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 352, 352, + 353, 199, 199, 82, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 355, + 355, 82, 82, 82, 82, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, + 356, 356, 356, 82, 356, 356, 356, 82, 357, 357, 82, 82, 82, 82, 358, 358, + 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 359, 359, 360, 359, + 359, 359, 359, 359, 359, 359, 360, 360, 360, 360, 360, 360, 360, 360, + 359, 360, 360, 359, 359, 359, 359, 359, 359, 359, 359, 359, 361, 359, + 362, 362, 363, 364, 362, 365, 362, 366, 358, 367, 82, 82, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 82, 82, 82, 82, 82, 82, 369, 369, 369, + 369, 369, 369, 369, 369, 369, 369, 82, 82, 82, 82, 82, 82, 370, 370, 371, + 371, 372, 373, 374, 370, 375, 375, 370, 376, 376, 376, 377, 82, 378, 378, + 378, 378, 378, 378, 378, 378, 378, 378, 82, 82, 82, 82, 82, 82, 379, 379, + 379, 379, 379, 379, 379, 379, 379, 379, 379, 380, 379, 379, 379, 379, + 379, 379, 379, 379, 379, 376, 376, 379, 379, 381, 379, 82, 82, 82, 82, + 82, 340, 340, 340, 340, 340, 340, 82, 82, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 82, 383, 383, 383, 384, 384, + 384, 384, 383, 383, 384, 384, 384, 82, 82, 82, 82, 384, 384, 383, 384, + 384, 384, 384, 384, 384, 385, 386, 387, 82, 82, 82, 82, 388, 82, 82, 82, + 389, 389, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 82, 82, 391, + 391, 391, 391, 391, 82, 82, 82, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 82, 82, 82, 82, 392, 392, 82, 82, 82, 82, 82, 82, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 394, 82, 82, 82, 395, + 395, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 398, 399, 400, 400, + 401, 82, 82, 402, 402, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 404, 405, 404, 405, 405, 405, 405, 405, 405, 405, 82, 406, + 404, 405, 404, 404, 405, 405, 405, 405, 405, 405, 405, 405, 404, 404, + 404, 404, 404, 404, 405, 405, 407, 407, 407, 407, 407, 407, 407, 407, 82, + 82, 408, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 82, 82, 82, + 82, 82, 82, 410, 410, 410, 410, 410, 410, 410, 411, 410, 410, 410, 410, + 410, 410, 82, 82, 97, 97, 97, 97, 97, 157, 157, 157, 157, 157, 157, 97, + 97, 157, 412, 82, 413, 413, 413, 413, 414, 415, 415, 415, 415, 415, 415, + 415, 415, 415, 415, 415, 415, 415, 415, 415, 416, 414, 413, 413, 413, + 413, 413, 414, 413, 414, 414, 414, 414, 414, 413, 414, 417, 415, 415, + 415, 415, 415, 415, 415, 82, 82, 82, 82, 418, 418, 418, 418, 418, 418, + 418, 418, 418, 418, 419, 419, 420, 419, 419, 419, 419, 421, 421, 421, + 421, 421, 421, 421, 421, 421, 421, 422, 423, 422, 422, 422, 422, 422, + 422, 422, 421, 421, 421, 421, 421, 421, 421, 421, 421, 82, 82, 82, 424, + 424, 425, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, + 426, 426, 425, 424, 424, 424, 424, 425, 425, 424, 424, 427, 428, 424, + 424, 426, 426, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 426, + 426, 426, 426, 426, 426, 430, 430, 430, 430, 430, 430, 430, 430, 430, + 430, 430, 430, 430, 430, 431, 432, 433, 433, 432, 432, 432, 433, 432, + 433, 433, 433, 434, 434, 82, 82, 82, 82, 82, 82, 82, 82, 435, 435, 435, + 435, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 437, + 437, 437, 437, 437, 437, 437, 437, 438, 438, 438, 438, 438, 438, 438, + 438, 437, 437, 438, 439, 82, 82, 82, 440, 440, 440, 440, 440, 441, 441, + 441, 441, 441, 441, 441, 441, 441, 441, 82, 82, 82, 436, 436, 436, 442, + 442, 442, 442, 442, 442, 442, 442, 442, 442, 443, 443, 443, 443, 443, + 443, 443, 443, 443, 443, 443, 443, 443, 443, 444, 444, 444, 444, 444, + 444, 445, 445, 94, 82, 82, 82, 82, 82, 82, 82, 446, 446, 446, 446, 446, + 446, 446, 446, 97, 97, 97, 326, 447, 157, 157, 157, 157, 157, 97, 97, + 157, 157, 157, 157, 97, 448, 447, 447, 447, 447, 447, 447, 447, 449, 449, + 449, 449, 157, 449, 449, 449, 449, 448, 448, 97, 449, 449, 82, 97, 97, + 82, 82, 82, 82, 82, 82, 57, 57, 57, 57, 57, 57, 80, 80, 80, 80, 80, 94, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 83, 83, 83, 83, 83, 60, 60, 60, 60, + 83, 83, 83, 83, 83, 57, 57, 57, 57, 57, 450, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 83, 97, 97, + 157, 97, 97, 97, 97, 97, 97, 97, 157, 97, 97, 451, 452, 157, 453, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 82, 82, 82, 82, 82, 97, 454, 157, 97, 157, 53, 57, 53, 57, 53, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 53, 57, 80, 80, 80, 80, 80, 80, 80, 80, + 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 82, 82, 79, 79, + 79, 79, 79, 79, 82, 82, 82, 79, 82, 79, 82, 79, 82, 79, 455, 455, 455, + 455, 455, 455, 455, 455, 80, 80, 80, 80, 80, 82, 80, 80, 79, 79, 79, 79, + 455, 81, 80, 81, 81, 81, 80, 80, 80, 82, 80, 80, 79, 79, 79, 79, 455, 81, + 81, 81, 80, 80, 80, 80, 82, 82, 80, 80, 79, 79, 79, 79, 82, 81, 81, 81, + 79, 79, 79, 79, 79, 81, 81, 81, 82, 82, 80, 80, 80, 82, 80, 80, 79, 79, + 79, 79, 455, 456, 81, 82, 457, 457, 457, 457, 457, 457, 457, 458, 457, + 457, 457, 459, 460, 461, 462, 463, 464, 465, 466, 464, 467, 468, 39, 85, + 469, 470, 471, 472, 469, 470, 471, 472, 39, 39, 473, 85, 474, 474, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 34, 483, 484, 483, 483, 484, 485, + 486, 486, 85, 43, 51, 39, 487, 487, 473, 488, 488, 85, 85, 85, 489, 490, + 491, 487, 487, 487, 85, 85, 85, 85, 85, 85, 85, 85, 492, 85, 488, 85, + 373, 85, 373, 373, 373, 373, 85, 373, 373, 457, 493, 494, 494, 494, 494, + 82, 495, 496, 497, 498, 499, 499, 499, 499, 499, 499, 500, 60, 82, 82, + 48, 500, 500, 500, 500, 500, 501, 501, 492, 490, 491, 502, 500, 48, 48, + 48, 48, 500, 500, 500, 500, 500, 501, 501, 492, 490, 491, 82, 60, 60, 60, + 60, 60, 82, 82, 82, 278, 278, 278, 278, 278, 278, 278, 503, 278, 504, + 278, 278, 37, 278, 278, 278, 278, 278, 278, 278, 278, 278, 503, 278, 278, + 278, 278, 503, 278, 278, 503, 505, 505, 505, 505, 505, 505, 505, 505, + 505, 97, 97, 447, 447, 97, 97, 97, 97, 447, 447, 447, 97, 97, 412, 412, + 412, 412, 97, 412, 412, 412, 447, 447, 97, 157, 97, 447, 447, 157, 157, + 157, 157, 97, 82, 82, 82, 82, 82, 82, 82, 41, 41, 506, 507, 41, 508, 41, + 506, 41, 507, 50, 506, 506, 506, 50, 50, 506, 506, 506, 509, 41, 506, + 510, 41, 492, 506, 506, 506, 506, 506, 41, 41, 41, 508, 508, 41, 506, 41, + 86, 41, 506, 41, 53, 511, 506, 506, 512, 50, 506, 506, 53, 506, 50, 449, + 449, 449, 449, 50, 41, 41, 50, 50, 506, 506, 513, 492, 492, 492, 492, + 506, 50, 50, 50, 50, 41, 492, 41, 41, 57, 313, 514, 514, 514, 515, 52, + 516, 514, 514, 514, 514, 514, 52, 515, 515, 52, 514, 517, 517, 517, 517, + 517, 517, 517, 517, 517, 517, 517, 517, 518, 518, 518, 518, 517, 517, + 518, 518, 518, 518, 518, 518, 518, 518, 518, 53, 57, 518, 518, 518, 518, + 52, 41, 41, 82, 82, 82, 82, 55, 55, 55, 55, 55, 508, 508, 508, 508, 508, + 492, 492, 41, 41, 41, 41, 492, 41, 41, 492, 41, 41, 492, 41, 41, 41, 41, + 41, 41, 41, 492, 41, 41, 41, 41, 41, 41, 41, 41, 41, 45, 45, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 492, 492, 41, 41, 55, 41, 55, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 45, 41, 41, 41, 41, 492, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 55, 513, 519, 519, 513, 492, 492, + 55, 519, 513, 513, 519, 513, 513, 492, 55, 492, 519, 520, 521, 492, 519, + 513, 492, 492, 492, 519, 513, 513, 519, 55, 519, 519, 513, 513, 55, 513, + 55, 513, 55, 55, 55, 55, 519, 519, 513, 519, 513, 513, 513, 513, 513, 55, + 55, 55, 55, 492, 513, 492, 513, 519, 519, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 519, 513, 513, 513, 519, 492, 492, 492, 492, 492, + 519, 513, 513, 513, 492, 492, 492, 492, 492, 492, 492, 492, 492, 513, + 519, 55, 513, 492, 519, 519, 519, 519, 513, 513, 519, 519, 492, 492, 519, + 519, 513, 513, 519, 519, 513, 513, 519, 519, 513, 513, 513, 513, 513, + 492, 492, 513, 513, 513, 513, 492, 492, 55, 492, 492, 513, 55, 492, 492, + 492, 492, 492, 492, 492, 492, 513, 513, 492, 55, 513, 513, 513, 492, 492, + 492, 492, 492, 513, 519, 492, 513, 513, 513, 513, 513, 492, 492, 513, + 513, 492, 492, 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 492, + 522, 490, 491, 490, 491, 41, 41, 41, 41, 41, 41, 508, 41, 41, 41, 41, 41, + 41, 41, 523, 523, 41, 41, 41, 41, 513, 513, 41, 41, 41, 41, 41, 41, 41, + 524, 525, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 313, 313, 313, 313, + 313, 313, 313, 313, 313, 313, 313, 313, 313, 41, 492, 41, 41, 41, 41, 41, + 41, 41, 41, 313, 41, 41, 41, 41, 41, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 41, 41, 41, 41, 492, 492, 41, 41, 41, 41, 41, 41, 41, 526, 526, + 526, 526, 41, 41, 41, 523, 527, 527, 523, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 82, 41, 41, 41, 82, 82, 82, 82, 82, 52, 52, 52, 52, 52, 52, + 52, 52, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 528, 528, 528, + 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 516, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 515, 508, 508, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 508, 41, 41, 41, 41, 508, 508, 508, 508, 529, + 41, 41, 41, 41, 41, 508, 508, 508, 508, 41, 41, 508, 508, 41, 508, 508, + 508, 508, 508, 508, 508, 41, 41, 41, 41, 41, 41, 41, 41, 508, 508, 41, + 41, 508, 55, 41, 41, 41, 41, 508, 508, 41, 41, 508, 55, 41, 41, 41, 41, + 508, 508, 508, 41, 41, 508, 41, 41, 508, 508, 41, 41, 41, 41, 41, 41, 41, + 508, 492, 492, 492, 492, 492, 530, 530, 492, 527, 527, 527, 527, 41, 508, + 508, 41, 41, 508, 41, 41, 41, 41, 508, 508, 41, 41, 41, 41, 523, 523, + 529, 529, 527, 41, 527, 527, 531, 532, 531, 527, 41, 527, 527, 527, 41, + 41, 41, 41, 508, 41, 508, 41, 41, 41, 41, 41, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 41, 41, 41, 41, 508, 508, 41, 508, + 508, 508, 41, 508, 531, 508, 508, 41, 508, 508, 41, 55, 41, 41, 41, 41, + 41, 41, 41, 523, 41, 41, 41, 526, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 508, 508, 41, 526, 41, 41, 41, 41, 41, 41, 41, 41, 526, 526, 313, 41, 41, + 41, 41, 41, 41, 41, 41, 523, 523, 531, 527, 527, 527, 527, 523, 523, 531, + 531, 531, 508, 508, 508, 508, 531, 526, 531, 531, 531, 508, 531, 523, + 508, 508, 508, 531, 531, 508, 508, 531, 508, 508, 531, 531, 531, 41, 508, + 41, 41, 41, 41, 508, 508, 523, 508, 508, 508, 508, 508, 508, 531, 523, + 523, 531, 523, 508, 531, 531, 533, 523, 508, 508, 523, 531, 531, 527, + 527, 527, 527, 527, 526, 41, 41, 527, 527, 534, 534, 532, 532, 41, 41, + 526, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 45, 41, 41, 41, 41, + 41, 41, 526, 41, 526, 41, 41, 41, 41, 526, 526, 526, 41, 535, 41, 41, 41, + 536, 536, 536, 536, 536, 536, 41, 537, 537, 527, 41, 41, 41, 490, 491, + 490, 491, 490, 491, 490, 491, 490, 491, 490, 491, 490, 491, 52, 52, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 41, 526, 526, 526, + 41, 41, 41, 41, 41, 41, 41, 526, 513, 492, 492, 513, 513, 490, 491, 492, + 513, 513, 492, 513, 513, 513, 492, 492, 492, 492, 492, 513, 513, 513, + 513, 492, 492, 492, 492, 492, 513, 513, 513, 492, 492, 492, 513, 513, + 513, 513, 16, 32, 16, 32, 16, 32, 16, 32, 490, 491, 538, 538, 538, 538, + 538, 538, 538, 538, 492, 492, 492, 490, 491, 16, 32, 490, 491, 490, 491, + 490, 491, 490, 491, 490, 491, 492, 492, 513, 513, 513, 513, 513, 513, + 492, 492, 492, 492, 492, 492, 492, 513, 513, 513, 513, 513, 513, 492, + 492, 492, 513, 492, 492, 492, 492, 513, 513, 513, 513, 513, 492, 513, + 513, 492, 492, 490, 491, 490, 491, 513, 492, 492, 492, 492, 513, 492, + 513, 513, 513, 492, 492, 513, 513, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 513, 513, 513, 513, 513, 513, 492, 492, 490, 491, 492, + 492, 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 492, 513, 513, 513, 513, 492, 492, 513, 492, 513, 492, 492, 513, 492, + 513, 513, 513, 513, 492, 492, 492, 492, 492, 513, 513, 492, 492, 492, + 492, 513, 513, 513, 513, 492, 513, 513, 492, 492, 513, 513, 492, 492, + 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 492, + 492, 513, 513, 513, 513, 513, 513, 513, 513, 492, 513, 513, 513, 513, + 513, 513, 513, 513, 492, 492, 492, 492, 492, 513, 492, 513, 492, 492, + 492, 513, 513, 513, 513, 513, 492, 492, 492, 492, 513, 492, 492, 492, + 513, 513, 513, 513, 513, 492, 513, 492, 492, 41, 41, 41, 526, 526, 41, + 41, 41, 492, 492, 492, 492, 492, 41, 41, 492, 492, 492, 492, 492, 492, + 41, 41, 41, 526, 41, 41, 41, 41, 535, 508, 508, 41, 41, 41, 41, 82, 82, + 41, 41, 41, 41, 41, 41, 41, 41, 82, 82, 41, 41, 82, 82, 82, 41, 41, 41, + 41, 82, 41, 41, 41, 41, 41, 41, 41, 41, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 41, 41, 41, 41, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, + 539, 539, 539, 539, 539, 82, 540, 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 82, 53, 57, 53, 53, 53, 57, 57, 53, 57, 53, + 57, 53, 57, 53, 53, 53, 53, 57, 53, 57, 57, 53, 57, 57, 57, 57, 57, 57, + 60, 60, 53, 53, 88, 89, 88, 89, 89, 541, 541, 541, 541, 541, 541, 88, 89, + 88, 89, 542, 542, 542, 88, 89, 82, 82, 82, 82, 82, 543, 544, 544, 544, + 545, 543, 544, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, + 546, 546, 546, 82, 546, 82, 82, 82, 82, 82, 546, 82, 82, 547, 547, 547, + 547, 547, 547, 547, 547, 82, 82, 82, 82, 82, 82, 82, 548, 549, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 550, 96, 96, 96, 96, 96, + 96, 96, 96, 551, 551, 43, 51, 43, 51, 551, 551, 551, 43, 51, 551, 43, 51, + 373, 373, 373, 373, 373, 373, 373, 373, 85, 466, 552, 373, 553, 85, 43, + 51, 85, 85, 43, 51, 490, 491, 490, 491, 490, 491, 490, 491, 373, 373, + 373, 373, 371, 61, 373, 373, 85, 373, 373, 85, 85, 85, 85, 85, 554, 554, + 373, 373, 373, 85, 466, 373, 471, 373, 373, 82, 82, 82, 555, 555, 555, + 555, 555, 555, 555, 555, 555, 555, 82, 555, 555, 555, 555, 555, 555, 555, + 555, 555, 82, 82, 82, 82, 555, 555, 555, 555, 555, 555, 82, 82, 523, 523, + 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 82, 82, 82, 82, 556, + 557, 557, 558, 523, 559, 560, 561, 524, 525, 524, 525, 524, 525, 524, + 525, 524, 525, 523, 523, 524, 525, 524, 525, 524, 525, 524, 525, 562, + 563, 564, 564, 523, 561, 561, 561, 561, 561, 561, 561, 561, 561, 565, + 566, 567, 568, 569, 569, 570, 571, 571, 571, 571, 572, 523, 523, 561, + 561, 561, 559, 573, 558, 523, 527, 82, 574, 575, 574, 575, 574, 575, 574, + 575, 574, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, + 575, 575, 575, 575, 575, 574, 575, 575, 575, 575, 575, 575, 575, 574, + 575, 574, 575, 574, 575, 575, 575, 575, 575, 575, 574, 575, 575, 575, + 575, 575, 575, 574, 574, 82, 82, 576, 576, 577, 577, 578, 578, 575, 562, + 579, 580, 579, 580, 579, 580, 579, 580, 579, 580, 580, 580, 580, 580, + 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 579, 580, + 580, 580, 580, 580, 580, 580, 579, 580, 579, 580, 579, 580, 580, 580, + 580, 580, 580, 579, 580, 580, 580, 580, 580, 580, 579, 579, 580, 580, + 580, 580, 581, 582, 583, 583, 580, 82, 82, 82, 82, 82, 584, 584, 584, + 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 82, + 82, 82, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 585, 585, 585, 585, 585, 82, 586, 586, 587, 587, 587, + 587, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 584, 584, 584, 82, + 82, 82, 82, 82, 579, 579, 579, 579, 579, 579, 579, 579, 588, 588, 588, + 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 589, 589, 82, 587, 587, + 587, 587, 587, 587, 587, 587, 587, 587, 586, 586, 586, 586, 586, 586, + 590, 590, 590, 590, 590, 590, 590, 590, 523, 591, 591, 591, 591, 591, + 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 588, 588, 588, 588, + 589, 589, 589, 586, 586, 591, 591, 591, 591, 591, 591, 591, 586, 586, + 586, 586, 523, 523, 523, 523, 592, 592, 592, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 592, 592, 82, 586, 586, 586, 586, 586, 586, 586, + 523, 523, 523, 523, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 523, 523, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, + 593, 593, 593, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595, + 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 596, 595, + 595, 595, 595, 595, 595, 595, 82, 82, 82, 597, 597, 597, 597, 597, 597, + 597, 597, 597, 597, 597, 597, 597, 597, 597, 82, 598, 598, 598, 598, 598, + 598, 598, 598, 599, 599, 599, 599, 599, 599, 600, 600, 601, 601, 601, + 601, 601, 601, 601, 601, 601, 601, 601, 601, 602, 603, 604, 603, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 601, 601, 82, 82, 82, 82, + 91, 94, 91, 94, 91, 94, 606, 96, 98, 98, 98, 607, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 607, 608, 91, 94, 91, 94, 450, 450, 96, 96, 609, 609, + 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 610, 610, + 610, 610, 610, 610, 610, 610, 610, 610, 611, 611, 612, 613, 613, 613, + 613, 613, 63, 63, 63, 63, 63, 63, 63, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 63, 63, 53, 57, 53, 57, 53, 57, 57, 57, 53, 57, 53, 57, 53, 57, 60, 57, + 57, 57, 57, 57, 57, 57, 57, 53, 57, 53, 57, 53, 53, 57, 61, 614, 614, 53, + 57, 53, 57, 58, 53, 57, 53, 57, 57, 57, 53, 57, 53, 57, 53, 53, 53, 53, + 53, 82, 53, 53, 53, 53, 53, 57, 53, 57, 82, 82, 82, 82, 82, 82, 82, 58, + 60, 60, 57, 58, 58, 58, 58, 58, 615, 615, 616, 615, 615, 615, 617, 615, + 615, 615, 615, 616, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, + 615, 615, 615, 615, 615, 618, 618, 616, 616, 618, 619, 619, 619, 619, 82, + 82, 82, 82, 620, 620, 620, 620, 620, 620, 313, 313, 503, 512, 82, 82, 82, + 82, 82, 82, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, + 622, 622, 623, 623, 624, 624, 625, 625, 625, 625, 625, 625, 625, 625, + 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 624, 624, 624, 624, + 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 626, 627, 82, + 82, 82, 82, 82, 82, 82, 82, 628, 628, 629, 629, 629, 629, 629, 629, 629, + 629, 629, 629, 82, 82, 82, 82, 82, 82, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 195, 195, 195, 195, 195, 195, 201, 201, 201, 195, 630, + 195, 82, 82, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 633, 633, 633, 633, 633, 634, 634, 634, 199, 635, + 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, + 636, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 638, 639, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 640, 328, 328, 328, 328, 328, 82, + 82, 82, 641, 641, 641, 642, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 644, 642, 642, 641, 641, 641, 641, 642, + 642, 641, 642, 642, 642, 645, 646, 646, 646, 646, 646, 646, 647, 647, + 647, 646, 646, 646, 646, 82, 62, 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 82, 82, 82, 82, 646, 646, 314, 314, 314, 314, 314, 316, 649, + 314, 319, 319, 314, 314, 314, 314, 314, 82, 650, 650, 650, 650, 650, 650, + 650, 650, 650, 651, 651, 651, 651, 651, 651, 652, 652, 651, 651, 652, + 652, 651, 651, 82, 650, 650, 650, 651, 650, 650, 650, 650, 650, 650, 650, + 650, 651, 652, 82, 82, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, + 82, 82, 654, 655, 655, 655, 649, 314, 314, 314, 314, 314, 314, 323, 323, + 323, 314, 315, 316, 315, 314, 314, 656, 656, 656, 656, 656, 656, 656, + 656, 657, 656, 657, 657, 658, 656, 656, 657, 657, 656, 656, 656, 656, + 656, 657, 657, 656, 657, 656, 82, 82, 82, 82, 82, 82, 82, 82, 656, 656, + 659, 660, 660, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, + 662, 663, 663, 662, 662, 664, 664, 661, 665, 665, 662, 666, 82, 82, 331, + 331, 331, 331, 331, 331, 82, 57, 57, 57, 614, 60, 60, 60, 60, 57, 57, 57, + 57, 57, 80, 82, 82, 338, 338, 338, 338, 338, 338, 338, 338, 661, 661, + 661, 662, 662, 663, 662, 662, 663, 662, 662, 664, 662, 666, 82, 82, 667, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 82, 82, 82, 82, 82, 82, 668, + 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, + 669, 669, 669, 669, 669, 668, 669, 669, 669, 669, 669, 669, 669, 82, 82, + 82, 82, 329, 329, 329, 329, 329, 329, 329, 82, 82, 82, 82, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 82, 82, 82, 82, 670, 670, 670, 670, 670, + 670, 670, 670, 671, 671, 671, 671, 671, 671, 671, 671, 593, 593, 594, + 594, 594, 594, 594, 594, 57, 57, 57, 57, 57, 57, 57, 82, 82, 82, 82, 102, + 102, 102, 102, 102, 82, 82, 82, 82, 82, 130, 672, 130, 130, 673, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 82, 130, 130, + 130, 130, 130, 82, 130, 82, 130, 130, 82, 130, 130, 82, 130, 130, 147, + 147, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, + 674, 674, 674, 82, 82, 82, 82, 82, 82, 82, 82, 82, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 675, 471, 82, 82, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 136, 139, 82, 82, 676, 676, 676, 676, 676, + 676, 676, 676, 677, 557, 557, 677, 677, 678, 678, 563, 564, 679, 82, 82, + 82, 82, 82, 82, 97, 97, 97, 97, 97, 97, 97, 157, 157, 157, 157, 157, 157, + 157, 96, 96, 558, 570, 570, 680, 680, 563, 564, 563, 564, 563, 564, 563, + 564, 563, 564, 563, 564, 563, 564, 563, 564, 558, 558, 563, 564, 558, + 558, 558, 558, 680, 680, 680, 681, 558, 681, 82, 581, 682, 678, 678, 570, + 524, 525, 524, 525, 524, 525, 683, 558, 558, 684, 685, 686, 686, 687, 82, + 558, 688, 689, 558, 82, 82, 82, 82, 147, 147, 147, 147, 147, 82, 82, 493, + 82, 690, 691, 692, 693, 694, 691, 691, 695, 696, 691, 697, 698, 699, 698, + 700, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 702, 703, 704, + 705, 704, 690, 691, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, + 706, 706, 706, 706, 706, 706, 706, 706, 695, 691, 696, 707, 708, 707, + 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, + 709, 709, 709, 709, 695, 705, 696, 705, 695, 696, 710, 711, 712, 710, + 713, 714, 715, 715, 715, 715, 715, 715, 715, 715, 715, 716, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, - 714, 714, 714, 714, 714, 714, 64, 64, 64, 715, 715, 715, 715, 715, 715, - 715, 715, 715, 715, 64, 715, 715, 715, 715, 715, 715, 715, 715, 715, 716, - 716, 716, 717, 717, 717, 716, 716, 717, 718, 719, 717, 720, 720, 720, - 720, 720, 720, 64, 64, 721, 721, 721, 721, 721, 721, 721, 64, 721, 64, - 721, 721, 721, 721, 64, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, - 721, 721, 721, 721, 721, 64, 721, 721, 722, 64, 64, 64, 64, 64, 64, 723, - 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, - 724, 725, 725, 725, 724, 724, 724, 724, 724, 724, 726, 727, 64, 64, 64, - 64, 64, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 64, 64, 64, 64, - 64, 64, 729, 729, 730, 730, 64, 731, 731, 731, 731, 731, 731, 731, 731, - 64, 64, 731, 731, 64, 64, 731, 731, 731, 731, 731, 731, 731, 731, 731, - 731, 731, 731, 731, 731, 64, 731, 731, 731, 731, 731, 731, 731, 64, 731, - 731, 64, 731, 731, 731, 731, 731, 64, 64, 732, 731, 730, 730, 729, 730, - 730, 730, 730, 64, 64, 730, 730, 64, 64, 730, 730, 733, 64, 64, 731, 64, - 64, 64, 64, 64, 64, 730, 64, 64, 64, 64, 64, 731, 731, 731, 731, 731, - 730, 730, 64, 64, 734, 734, 734, 734, 734, 734, 734, 64, 64, 64, 735, - 735, 735, 735, 735, 735, 735, 735, 736, 736, 736, 737, 737, 737, 737, - 737, 737, 736, 737, 736, 736, 736, 736, 737, 737, 736, 738, 739, 735, - 735, 740, 735, 741, 741, 741, 741, 741, 741, 741, 741, 741, 741, 64, 64, - 64, 64, 64, 64, 742, 742, 742, 742, 742, 742, 742, 742, 742, 742, 742, - 742, 742, 742, 742, 743, 743, 743, 744, 744, 744, 744, 64, 64, 743, 743, - 743, 743, 744, 744, 743, 745, 746, 747, 747, 747, 747, 747, 747, 747, - 747, 747, 747, 747, 747, 747, 747, 747, 742, 742, 742, 742, 744, 744, 64, - 64, 748, 748, 748, 748, 748, 748, 748, 748, 749, 749, 749, 750, 750, 750, - 750, 750, 750, 750, 750, 749, 749, 750, 749, 751, 750, 752, 752, 752, - 748, 64, 64, 64, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 64, - 64, 64, 64, 64, 64, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, - 754, 755, 756, 755, 756, 756, 755, 755, 755, 755, 755, 755, 757, 758, - 759, 759, 759, 759, 759, 759, 759, 759, 759, 759, 64, 64, 64, 64, 64, 64, - 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, 64, 64, 64, 761, 761, - 761, 762, 762, 761, 761, 761, 761, 762, 761, 761, 761, 761, 763, 64, 64, - 64, 64, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 765, 765, 766, - 766, 766, 767, 768, 768, 768, 768, 768, 768, 768, 768, 769, 769, 769, - 769, 769, 769, 769, 769, 770, 770, 770, 770, 770, 770, 770, 770, 770, - 770, 771, 771, 771, 771, 771, 771, 771, 771, 771, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 772, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 64, 64, 64, 64, 64, 64, 64, 774, 774, 774, 774, 774, 774, 774, 774, 774, - 774, 64, 64, 64, 64, 64, 64, 775, 775, 775, 775, 775, 775, 775, 775, 775, - 775, 775, 775, 775, 775, 775, 64, 776, 776, 776, 776, 776, 64, 64, 64, - 774, 774, 774, 774, 64, 64, 64, 64, 777, 777, 777, 777, 777, 777, 777, - 777, 777, 777, 777, 777, 777, 777, 777, 64, 778, 778, 778, 778, 778, 778, - 778, 778, 778, 778, 778, 778, 778, 778, 778, 64, 511, 64, 64, 64, 64, 64, - 64, 64, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, - 779, 779, 64, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 64, 64, - 64, 64, 781, 781, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, - 782, 782, 782, 64, 64, 783, 783, 783, 783, 783, 784, 64, 64, 785, 785, - 785, 785, 785, 785, 785, 785, 786, 786, 786, 786, 786, 786, 786, 787, - 787, 787, 787, 787, 788, 788, 788, 788, 789, 789, 789, 789, 787, 788, 64, - 64, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 64, 791, 791, 791, - 791, 791, 791, 791, 64, 785, 785, 785, 785, 785, 64, 64, 64, 64, 64, 785, - 785, 785, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, - 792, 64, 64, 64, 792, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, - 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 64, 64, 64, - 64, 64, 64, 64, 64, 794, 794, 794, 794, 795, 795, 795, 795, 795, 795, - 795, 795, 795, 795, 795, 795, 795, 486, 482, 64, 64, 64, 64, 64, 64, 796, - 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 64, 64, 64, 64, 64, - 796, 796, 796, 796, 796, 64, 64, 64, 796, 64, 64, 64, 64, 64, 64, 64, - 796, 796, 64, 64, 797, 798, 799, 800, 410, 410, 410, 410, 64, 64, 64, 64, - 277, 277, 277, 277, 277, 277, 64, 64, 277, 277, 277, 277, 277, 277, 277, - 64, 64, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 801, - 801, 400, 400, 400, 277, 277, 277, 802, 801, 801, 801, 801, 801, 410, - 410, 410, 410, 410, 410, 410, 410, 136, 136, 136, 136, 136, 136, 136, - 136, 277, 277, 78, 78, 78, 78, 78, 136, 136, 277, 277, 277, 277, 277, - 277, 78, 78, 78, 78, 277, 277, 277, 64, 64, 64, 64, 64, 64, 64, 606, 606, - 803, 803, 803, 606, 64, 64, 521, 521, 64, 64, 64, 64, 64, 64, 442, 442, - 442, 442, 442, 442, 442, 442, 442, 442, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 442, 442, 442, 442, 442, 442, - 442, 442, 442, 442, 34, 34, 34, 34, 34, 34, 34, 64, 34, 34, 34, 34, 34, - 34, 442, 64, 442, 442, 64, 64, 442, 64, 64, 442, 442, 64, 64, 442, 442, - 442, 442, 64, 442, 442, 34, 34, 64, 34, 64, 34, 34, 34, 34, 34, 34, 34, - 64, 34, 34, 34, 34, 34, 34, 34, 442, 442, 64, 442, 442, 442, 442, 64, 64, - 442, 442, 442, 442, 442, 442, 442, 442, 64, 442, 442, 442, 442, 442, 442, - 442, 64, 34, 34, 442, 442, 64, 442, 442, 442, 442, 64, 442, 442, 442, - 442, 442, 64, 442, 64, 64, 64, 442, 442, 442, 442, 442, 442, 442, 64, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 64, 64, 442, 804, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 445, 34, 34, 34, 34, 34, 34, 442, 442, 442, 442, - 442, 442, 442, 442, 442, 804, 34, 34, 34, 34, 34, 34, 34, 34, 34, 445, - 34, 34, 442, 442, 442, 442, 442, 804, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 445, 34, 34, 34, 34, 34, 34, 442, 442, 442, 442, 442, 442, 442, 442, 442, - 804, 34, 445, 34, 34, 34, 34, 34, 34, 34, 34, 442, 34, 64, 64, 805, 805, - 805, 805, 805, 805, 805, 805, 805, 805, 806, 806, 806, 806, 806, 806, - 806, 806, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, - 807, 807, 807, 806, 806, 806, 806, 807, 807, 807, 807, 807, 807, 807, - 807, 807, 807, 806, 806, 806, 806, 806, 806, 806, 806, 807, 806, 806, - 806, 806, 806, 806, 807, 806, 806, 808, 808, 808, 808, 808, 64, 64, 64, - 64, 64, 64, 64, 807, 807, 807, 807, 807, 64, 807, 807, 807, 807, 807, - 807, 807, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 64, 64, 810, 810, 810, 810, 810, 810, 810, 810, 810, 811, 811, 811, - 811, 811, 811, 811, 64, 126, 126, 126, 126, 64, 126, 126, 126, 64, 126, - 126, 64, 126, 64, 64, 126, 64, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 64, 126, 126, 126, 126, 64, 126, 64, 126, 64, 64, 64, 64, 64, - 64, 126, 64, 64, 64, 64, 126, 64, 126, 64, 126, 64, 126, 126, 126, 64, - 126, 64, 126, 64, 126, 64, 126, 64, 126, 126, 126, 126, 64, 126, 64, 126, - 126, 64, 126, 126, 126, 126, 126, 126, 126, 126, 126, 64, 64, 64, 64, 64, - 126, 126, 126, 64, 126, 126, 126, 113, 113, 64, 64, 64, 64, 64, 64, 64, - 26, 26, 26, 26, 26, 26, 26, 33, 33, 33, 446, 446, 64, 64, 64, 453, 453, - 453, 453, 453, 453, 277, 64, 453, 453, 26, 26, 64, 64, 64, 64, 453, 453, - 453, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 277, 277, 812, 489, 489, - 64, 64, 64, 64, 64, 489, 489, 489, 64, 64, 64, 64, 64, 489, 64, 64, 64, - 64, 64, 64, 64, 489, 489, 64, 64, 64, 64, 64, 64, 26, 26, 26, 47, 47, 47, - 47, 47, 26, 26, 64, 26, 26, 26, 26, 26, 26, 26, 26, 26, 64, 26, 26, 26, - 26, 64, 64, 64, 64, 64, 64, 64, 26, 26, 26, 26, 26, 64, 64, 64, 496, 496, - 496, 496, 496, 496, 496, 497, 496, 496, 496, 496, 496, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 64, 64, 64, 410, 64, 64, 64, 64, 64, 64, - 410, 410, 410, 410, 410, 410, 410, 410, 565, 565, 565, 565, 565, 565, 64, - 64, + 714, 714, 714, 714, 714, 717, 717, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, 82, 82, 82, 718, 718, 718, 718, + 718, 718, 82, 82, 718, 718, 718, 82, 82, 82, 719, 693, 705, 707, 720, + 693, 693, 82, 721, 722, 722, 722, 722, 721, 721, 82, 82, 723, 723, 723, + 724, 508, 82, 82, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, + 725, 82, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 82, 725, 725, + 725, 82, 725, 725, 82, 725, 725, 725, 725, 725, 725, 725, 82, 82, 725, + 725, 725, 82, 82, 82, 82, 82, 199, 373, 199, 82, 82, 82, 82, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 82, 82, 82, 313, + 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 727, + 727, 727, 727, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, + 728, 728, 728, 728, 728, 728, 727, 727, 728, 729, 729, 82, 41, 41, 41, + 41, 82, 82, 82, 82, 728, 82, 82, 82, 82, 82, 82, 82, 313, 313, 313, 313, + 313, 157, 82, 82, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, + 730, 730, 82, 82, 82, 731, 731, 731, 731, 731, 731, 731, 731, 731, 82, + 82, 82, 82, 82, 82, 82, 157, 500, 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 82, 82, 82, 82, 732, + 732, 732, 732, 732, 732, 732, 732, 733, 733, 733, 733, 82, 82, 82, 82, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 735, 734, 734, 734, 734, + 734, 734, 734, 734, 735, 82, 82, 82, 82, 82, 736, 736, 736, 736, 736, + 736, 736, 736, 736, 736, 736, 736, 736, 736, 737, 737, 737, 737, 737, 82, + 82, 82, 82, 82, 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 82, 739, 740, 740, 740, 740, 740, 740, 740, 740, 740, 740, + 740, 740, 82, 82, 82, 82, 741, 742, 742, 742, 742, 742, 82, 82, 743, 743, + 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 744, 744, + 745, 745, 745, 745, 745, 745, 745, 745, 746, 746, 746, 746, 746, 746, + 746, 746, 746, 746, 746, 746, 746, 746, 82, 82, 747, 747, 747, 747, 747, + 747, 747, 747, 747, 747, 82, 82, 82, 82, 82, 82, 748, 748, 748, 748, 748, + 748, 748, 748, 748, 748, 748, 748, 82, 82, 82, 82, 749, 749, 749, 749, + 749, 749, 749, 749, 749, 749, 749, 749, 82, 82, 82, 82, 750, 750, 750, + 750, 750, 750, 750, 750, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 751, 751, 751, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 752, 753, 753, + 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 82, 753, + 753, 753, 753, 753, 753, 82, 82, 754, 754, 754, 754, 754, 754, 82, 82, + 754, 82, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, + 754, 754, 754, 754, 754, 754, 754, 82, 754, 754, 82, 82, 82, 754, 82, 82, + 754, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, + 755, 82, 756, 757, 757, 757, 757, 757, 757, 757, 757, 758, 758, 758, 758, + 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 759, 759, 760, + 760, 760, 760, 760, 760, 760, 761, 761, 761, 761, 761, 761, 761, 761, + 761, 761, 761, 761, 761, 761, 761, 82, 82, 82, 82, 82, 82, 82, 82, 762, + 762, 762, 762, 762, 762, 762, 762, 762, 763, 763, 763, 763, 763, 763, + 763, 763, 763, 763, 763, 82, 763, 763, 82, 82, 82, 82, 82, 764, 764, 764, + 764, 764, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 766, 766, 766, 766, 766, 766, 82, 82, 82, 767, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 82, 82, 82, 82, 82, 769, 770, 770, + 770, 770, 770, 770, 770, 770, 771, 771, 771, 771, 771, 771, 771, 771, 82, + 82, 82, 82, 772, 772, 771, 771, 772, 772, 772, 772, 772, 772, 772, 772, + 82, 82, 772, 772, 772, 772, 772, 772, 773, 774, 774, 774, 82, 774, 774, + 82, 82, 82, 82, 82, 774, 775, 774, 776, 773, 773, 773, 773, 82, 773, 773, + 773, 82, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 82, 82, 82, 82, 776, 777, 775, 82, 82, 82, + 82, 778, 779, 779, 779, 779, 779, 779, 779, 779, 780, 780, 780, 780, 780, + 780, 780, 780, 781, 82, 82, 82, 82, 82, 82, 82, 782, 782, 782, 782, 782, + 782, 782, 782, 782, 782, 782, 782, 782, 783, 783, 784, 785, 785, 785, + 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 786, 786, 786, 787, + 787, 787, 787, 787, 787, 787, 787, 788, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 789, 790, 82, 82, 82, 82, 791, 791, 791, + 791, 791, 792, 792, 792, 792, 792, 792, 793, 82, 794, 794, 794, 794, 794, + 794, 794, 794, 794, 794, 794, 794, 794, 794, 82, 82, 82, 795, 795, 795, + 795, 795, 795, 795, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, + 796, 796, 796, 796, 82, 82, 797, 797, 797, 797, 797, 797, 797, 797, 798, + 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 82, 82, 82, 82, 82, + 799, 799, 799, 799, 799, 799, 799, 799, 800, 800, 800, 800, 800, 800, + 800, 800, 800, 800, 82, 82, 82, 82, 82, 82, 82, 801, 801, 801, 801, 82, + 82, 82, 82, 802, 802, 802, 802, 802, 802, 802, 803, 803, 803, 803, 803, + 803, 803, 803, 803, 82, 82, 82, 82, 82, 82, 82, 804, 804, 804, 804, 804, + 804, 804, 804, 804, 804, 804, 82, 82, 82, 82, 82, 805, 805, 805, 805, + 805, 805, 805, 805, 805, 805, 805, 82, 82, 82, 82, 82, 82, 82, 806, 806, + 806, 806, 806, 806, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, + 807, 807, 807, 807, 807, 82, 808, 809, 808, 810, 810, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 810, 809, 809, 809, 809, 809, 809, 809, + 809, 809, 809, 809, 809, 809, 809, 811, 812, 812, 813, 813, 813, 813, + 813, 82, 82, 82, 82, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, + 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 815, 815, 815, 815, + 815, 815, 815, 815, 815, 815, 82, 82, 82, 82, 82, 82, 82, 811, 816, 816, + 817, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, + 817, 817, 817, 816, 816, 816, 816, 817, 817, 819, 820, 821, 821, 822, + 823, 823, 823, 823, 82, 82, 82, 82, 82, 82, 824, 824, 824, 824, 824, 824, + 824, 824, 824, 82, 82, 82, 82, 82, 82, 82, 825, 825, 825, 825, 825, 825, + 825, 825, 825, 825, 82, 82, 82, 82, 82, 82, 826, 826, 826, 827, 827, 827, + 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, + 827, 827, 827, 828, 828, 828, 828, 828, 829, 828, 828, 828, 828, 828, + 828, 830, 830, 82, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 832, + 832, 832, 832, 82, 82, 82, 82, 833, 833, 833, 833, 833, 833, 833, 833, + 833, 833, 833, 834, 835, 836, 833, 82, 837, 837, 838, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 838, 838, + 838, 837, 837, 837, 837, 837, 837, 837, 837, 837, 838, 840, 839, 839, + 839, 839, 841, 841, 842, 841, 842, 843, 837, 837, 842, 82, 82, 844, 844, + 844, 844, 844, 844, 844, 844, 844, 844, 839, 845, 839, 841, 841, 841, 82, + 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 82, 82, 82, 847, 847, 847, 847, 847, 847, + 847, 847, 847, 847, 82, 847, 847, 847, 847, 847, 847, 847, 847, 847, 848, + 848, 848, 849, 849, 849, 848, 848, 849, 850, 851, 849, 852, 852, 853, + 852, 852, 853, 849, 82, 854, 854, 854, 854, 854, 854, 854, 82, 854, 82, + 854, 854, 854, 854, 82, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, + 854, 854, 854, 854, 854, 82, 854, 854, 855, 82, 82, 82, 82, 82, 82, 856, + 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, + 857, 858, 858, 858, 857, 857, 857, 857, 857, 857, 859, 860, 82, 82, 82, + 82, 82, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 82, 82, 82, 82, + 82, 82, 862, 862, 863, 863, 82, 864, 864, 864, 864, 864, 864, 864, 864, + 82, 82, 864, 864, 82, 82, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 864, 82, 864, 864, 864, 864, 864, 864, 864, 82, 864, + 864, 82, 864, 864, 864, 864, 864, 82, 82, 865, 864, 863, 863, 862, 863, + 863, 863, 863, 82, 82, 863, 863, 82, 82, 863, 863, 866, 82, 82, 864, 82, + 82, 82, 82, 82, 82, 863, 82, 82, 82, 82, 82, 864, 864, 864, 864, 864, + 863, 863, 82, 82, 867, 867, 867, 867, 867, 867, 867, 82, 82, 82, 868, + 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 869, 869, + 869, 870, 870, 870, 870, 870, 870, 870, 870, 869, 869, 871, 870, 870, + 869, 872, 868, 868, 868, 868, 873, 873, 873, 873, 874, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 82, 873, 82, 874, 82, 82, 876, 876, + 876, 876, 876, 876, 876, 876, 877, 877, 877, 878, 878, 878, 878, 878, + 878, 877, 878, 877, 877, 877, 877, 878, 878, 877, 879, 880, 876, 876, + 881, 876, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 82, 82, 82, + 82, 82, 82, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, + 883, 883, 883, 884, 884, 884, 885, 885, 885, 885, 82, 82, 884, 884, 884, + 884, 885, 885, 884, 886, 887, 888, 889, 889, 890, 890, 891, 891, 891, + 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, + 889, 883, 883, 883, 883, 885, 885, 82, 82, 892, 892, 892, 892, 892, 892, + 892, 892, 893, 893, 893, 894, 894, 894, 894, 894, 894, 894, 894, 893, + 893, 894, 893, 895, 894, 896, 896, 897, 892, 82, 82, 82, 898, 898, 898, + 898, 898, 898, 898, 898, 898, 898, 82, 82, 82, 82, 82, 82, 899, 899, 899, + 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 82, 82, 82, 900, 900, + 900, 900, 900, 900, 900, 900, 900, 900, 900, 901, 902, 901, 902, 902, + 901, 901, 901, 901, 901, 901, 903, 904, 905, 905, 905, 905, 905, 905, + 905, 905, 905, 905, 82, 82, 82, 82, 82, 82, 906, 906, 906, 906, 906, 906, + 906, 906, 906, 906, 82, 82, 82, 907, 907, 907, 908, 908, 907, 907, 907, + 907, 908, 907, 907, 907, 907, 909, 82, 82, 82, 82, 910, 910, 910, 910, + 910, 910, 910, 910, 910, 910, 911, 911, 912, 912, 912, 913, 914, 914, + 914, 914, 914, 914, 914, 914, 915, 915, 915, 915, 915, 915, 915, 915, + 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 917, 917, 917, 917, + 917, 917, 917, 917, 917, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 918, 919, 919, 919, 919, 919, 919, 919, 919, 919, 82, 82, 82, 82, 82, 82, + 82, 920, 920, 920, 920, 920, 920, 920, 920, 920, 82, 920, 920, 920, 920, + 920, 920, 920, 920, 920, 920, 920, 920, 920, 921, 922, 922, 922, 922, + 922, 922, 922, 82, 922, 922, 922, 922, 922, 922, 921, 923, 920, 924, 924, + 924, 924, 924, 82, 82, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 82, 82, 82, 927, 928, 929, 929, 929, 929, 929, + 929, 929, 929, 929, 929, 929, 929, 929, 929, 82, 82, 930, 930, 930, 930, + 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 82, 931, 930, 930, 930, + 930, 930, 930, 930, 931, 930, 930, 931, 930, 930, 82, 932, 932, 932, 932, + 932, 932, 932, 932, 932, 932, 82, 82, 82, 82, 82, 82, 933, 933, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 82, 934, 934, 934, + 934, 934, 82, 82, 82, 932, 932, 932, 932, 82, 82, 82, 82, 935, 935, 935, + 935, 935, 935, 935, 935, 936, 936, 936, 937, 937, 937, 935, 935, 935, + 935, 937, 935, 935, 935, 936, 937, 936, 937, 935, 935, 935, 935, 935, + 935, 935, 936, 937, 937, 935, 935, 935, 935, 935, 935, 935, 935, 935, + 935, 935, 82, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, + 938, 938, 939, 940, 938, 938, 938, 938, 938, 938, 938, 82, 609, 82, 82, + 82, 82, 82, 82, 82, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, + 941, 941, 941, 941, 941, 82, 942, 942, 942, 942, 942, 942, 942, 942, 942, + 942, 82, 82, 82, 82, 943, 943, 944, 944, 944, 944, 944, 944, 944, 944, + 944, 944, 944, 944, 944, 944, 82, 82, 945, 945, 945, 945, 945, 946, 82, + 82, 947, 947, 947, 947, 947, 947, 947, 947, 948, 948, 948, 948, 948, 948, + 948, 949, 949, 949, 950, 950, 951, 951, 951, 951, 952, 952, 952, 952, + 949, 951, 82, 82, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 82, + 954, 954, 954, 954, 954, 954, 954, 82, 947, 947, 947, 947, 947, 82, 82, + 82, 82, 82, 947, 947, 947, 955, 955, 955, 955, 955, 955, 955, 955, 955, + 955, 955, 955, 955, 82, 82, 82, 955, 956, 956, 956, 956, 956, 956, 956, + 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, + 956, 82, 82, 82, 82, 82, 82, 82, 82, 957, 957, 957, 957, 958, 958, 958, + 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 959, 82, 82, 82, 82, + 82, 82, 82, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, + 960, 82, 82, 82, 960, 960, 960, 82, 82, 82, 82, 82, 580, 575, 82, 82, 82, + 82, 82, 82, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 82, + 82, 82, 82, 82, 961, 961, 961, 961, 961, 82, 82, 82, 961, 82, 82, 82, 82, + 82, 82, 82, 961, 961, 82, 82, 962, 963, 964, 965, 499, 499, 499, 499, 82, + 82, 82, 82, 313, 313, 313, 313, 313, 313, 82, 82, 313, 313, 313, 313, + 313, 313, 313, 82, 82, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, + 313, 313, 966, 966, 447, 447, 447, 313, 313, 313, 967, 966, 966, 966, + 966, 966, 499, 499, 499, 499, 499, 499, 499, 499, 157, 157, 157, 157, + 157, 157, 157, 157, 313, 313, 97, 97, 97, 97, 97, 157, 157, 313, 313, + 313, 313, 313, 313, 97, 97, 97, 97, 313, 313, 313, 82, 82, 82, 82, 82, + 82, 82, 728, 728, 968, 968, 968, 728, 82, 82, 620, 620, 82, 82, 82, 82, + 82, 82, 506, 506, 506, 506, 506, 506, 506, 506, 506, 506, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 506, 506, 506, + 506, 506, 506, 506, 506, 506, 506, 50, 50, 50, 50, 50, 50, 50, 82, 50, + 50, 50, 50, 50, 50, 506, 82, 506, 506, 82, 82, 506, 82, 82, 506, 506, 82, + 82, 506, 506, 506, 506, 82, 506, 506, 50, 50, 82, 50, 82, 50, 50, 50, 50, + 50, 50, 50, 82, 50, 50, 50, 50, 50, 50, 50, 506, 506, 82, 506, 506, 506, + 506, 82, 82, 506, 506, 506, 506, 506, 506, 506, 506, 82, 506, 506, 506, + 506, 506, 506, 506, 82, 50, 50, 506, 506, 82, 506, 506, 506, 506, 82, + 506, 506, 506, 506, 506, 82, 506, 82, 82, 82, 506, 506, 506, 506, 506, + 506, 506, 82, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 82, 82, + 506, 969, 50, 50, 50, 50, 50, 50, 50, 50, 50, 513, 50, 50, 50, 50, 50, + 50, 506, 506, 506, 506, 506, 506, 506, 506, 506, 969, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 513, 50, 50, 506, 506, 506, 506, 506, 969, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 513, 50, 50, 50, 50, 50, 50, 506, 506, 506, 506, + 506, 506, 506, 506, 506, 969, 50, 513, 50, 50, 50, 50, 50, 50, 50, 50, + 506, 50, 82, 82, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 971, + 971, 971, 971, 971, 971, 971, 971, 972, 972, 972, 972, 972, 972, 972, + 972, 972, 972, 972, 972, 972, 972, 972, 971, 971, 971, 971, 972, 972, + 972, 972, 972, 972, 972, 972, 972, 972, 971, 971, 971, 971, 971, 971, + 971, 971, 972, 971, 971, 971, 971, 971, 971, 972, 971, 971, 973, 973, + 973, 973, 974, 82, 82, 82, 82, 82, 82, 82, 972, 972, 972, 972, 972, 82, + 972, 972, 972, 972, 972, 972, 972, 975, 975, 975, 975, 975, 975, 975, 82, + 975, 975, 975, 975, 975, 975, 975, 975, 975, 82, 82, 975, 975, 975, 975, + 975, 975, 975, 82, 975, 975, 82, 975, 975, 975, 975, 975, 82, 82, 82, 82, + 82, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 82, + 82, 977, 977, 977, 977, 977, 977, 977, 977, 977, 978, 978, 978, 978, 978, + 978, 978, 82, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 980, 980, + 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, + 980, 980, 981, 981, 981, 981, 981, 981, 982, 82, 82, 82, 82, 82, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 983, 82, 82, 82, 82, 984, 984, + 147, 147, 147, 147, 82, 147, 147, 147, 82, 147, 147, 82, 147, 82, 82, + 147, 82, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 82, 147, 147, + 147, 147, 82, 147, 82, 147, 82, 82, 82, 82, 82, 82, 147, 82, 82, 82, 82, + 147, 82, 147, 82, 147, 82, 147, 147, 147, 82, 147, 82, 147, 82, 147, 82, + 147, 82, 147, 147, 147, 147, 82, 147, 82, 147, 147, 82, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 82, 82, 82, 82, 82, 147, 147, 147, 82, 147, + 147, 147, 133, 133, 82, 82, 82, 82, 82, 82, 527, 527, 527, 527, 523, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 527, 527, + 527, 527, 527, 527, 527, 985, 985, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 523, 527, 527, 527, 527, 527, 527, + 985, 985, 48, 48, 48, 516, 516, 985, 985, 985, 528, 528, 528, 528, 528, + 528, 313, 985, 528, 528, 41, 41, 985, 985, 985, 985, 528, 528, 528, 528, + 528, 528, 986, 528, 528, 986, 986, 986, 986, 986, 986, 986, 986, 986, + 986, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 985, 985, 985, + 985, 985, 985, 985, 985, 985, 987, 987, 987, 987, 987, 987, 987, 987, + 987, 987, 988, 586, 586, 985, 985, 985, 985, 985, 586, 586, 586, 586, + 985, 985, 985, 985, 586, 985, 985, 985, 985, 985, 985, 985, 586, 586, + 985, 985, 985, 985, 985, 985, 523, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 523, 523, 523, 523, 523, 523, 523, 523, 523, + 527, 523, 523, 523, 523, 523, 523, 527, 523, 523, 523, 523, 523, 523, + 523, 534, 523, 523, 523, 523, 523, 523, 527, 527, 527, 527, 527, 527, + 527, 527, 41, 41, 527, 527, 523, 523, 523, 523, 523, 526, 526, 523, 523, + 523, 523, 523, 526, 523, 523, 523, 523, 523, 523, 534, 534, 523, 523, + 523, 523, 523, 534, 532, 527, 527, 527, 523, 523, 527, 527, 527, 523, + 527, 527, 527, 523, 523, 523, 989, 989, 989, 989, 989, 523, 523, 523, + 523, 523, 523, 523, 527, 523, 527, 534, 534, 523, 523, 534, 534, 534, + 534, 534, 534, 534, 534, 534, 534, 534, 523, 523, 523, 523, 523, 523, + 523, 523, 523, 523, 523, 523, 523, 534, 534, 534, 534, 523, 523, 523, + 523, 534, 523, 534, 523, 523, 523, 534, 523, 523, 523, 523, 534, 534, + 534, 523, 534, 534, 534, 526, 523, 526, 523, 526, 523, 523, 523, 523, + 523, 534, 523, 523, 523, 523, 526, 523, 526, 526, 523, 523, 523, 523, + 523, 523, 523, 523, 523, 523, 527, 527, 523, 526, 526, 526, 526, 526, + 526, 526, 523, 523, 523, 523, 523, 523, 523, 523, 526, 526, 526, 526, + 526, 526, 523, 523, 523, 523, 523, 526, 526, 526, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 41, 41, 41, 41, 527, 523, 523, 523, 523, 527, + 527, 527, 527, 527, 527, 532, 527, 527, 527, 527, 534, 527, 527, 527, + 527, 527, 532, 527, 527, 527, 527, 534, 534, 527, 527, 527, 527, 527, 41, + 41, 41, 41, 41, 41, 41, 41, 527, 527, 527, 527, 41, 41, 527, 523, 523, + 523, 523, 523, 523, 523, 523, 523, 523, 534, 534, 534, 523, 523, 523, + 534, 534, 534, 534, 534, 41, 41, 41, 41, 41, 41, 536, 536, 536, 990, 990, + 990, 41, 41, 41, 41, 523, 523, 523, 534, 523, 523, 523, 523, 523, 523, + 523, 523, 534, 534, 534, 523, 534, 523, 523, 523, 523, 523, 527, 527, + 523, 523, 523, 985, 985, 985, 985, 985, 527, 527, 527, 523, 523, 985, + 985, 985, 527, 527, 527, 527, 523, 523, 523, 985, 41, 41, 41, 41, 985, + 985, 985, 985, 41, 41, 41, 41, 41, 985, 985, 985, 41, 41, 985, 985, 985, + 985, 985, 985, 41, 41, 41, 41, 41, 41, 985, 985, 534, 534, 534, 534, 534, + 534, 534, 985, 523, 523, 523, 523, 523, 523, 534, 523, 534, 985, 985, + 534, 534, 534, 534, 534, 534, 534, 523, 523, 534, 534, 534, 985, 523, + 523, 523, 523, 985, 985, 985, 985, 523, 523, 523, 523, 523, 523, 523, + 985, 523, 523, 985, 985, 985, 985, 985, 985, 523, 985, 985, 985, 985, + 985, 985, 985, 985, 985, 985, 985, 985, 985, 82, 82, 593, 593, 593, 593, + 593, 593, 593, 594, 593, 593, 593, 593, 593, 594, 594, 594, 594, 594, + 594, 594, 594, 594, 82, 82, 82, 499, 82, 82, 82, 82, 82, 82, 499, 499, + 499, 499, 499, 499, 499, 499, 671, 671, 671, 671, 671, 671, 82, 82, }; /* decomposition data */ @@ -3874,98 +4326,98 @@ static const unsigned short decomp_data[] = { 25429, 266, 19968, 266, 19977, 266, 36938, 266, 24038, 266, 20013, 266, 21491, 266, 25351, 266, 36208, 266, 25171, 266, 31105, 266, 31354, 266, 21512, 266, 28288, 266, 26377, 266, 26376, 266, 30003, 266, 21106, 266, - 21942, 770, 12308, 26412, 12309, 770, 12308, 19977, 12309, 770, 12308, - 20108, 12309, 770, 12308, 23433, 12309, 770, 12308, 28857, 12309, 770, - 12308, 25171, 12309, 770, 12308, 30423, 12309, 770, 12308, 21213, 12309, - 770, 12308, 25943, 12309, 263, 24471, 263, 21487, 256, 20029, 256, 20024, - 256, 20033, 256, 55360, 56610, 256, 20320, 256, 20398, 256, 20411, 256, - 20482, 256, 20602, 256, 20633, 256, 20711, 256, 20687, 256, 13470, 256, - 55361, 56890, 256, 20813, 256, 20820, 256, 20836, 256, 20855, 256, 55361, - 56604, 256, 13497, 256, 20839, 256, 20877, 256, 55361, 56651, 256, 20887, - 256, 20900, 256, 20172, 256, 20908, 256, 20917, 256, 55396, 56799, 256, - 20981, 256, 20995, 256, 13535, 256, 21051, 256, 21062, 256, 21106, 256, - 21111, 256, 13589, 256, 21191, 256, 21193, 256, 21220, 256, 21242, 256, - 21253, 256, 21254, 256, 21271, 256, 21321, 256, 21329, 256, 21338, 256, - 21363, 256, 21373, 256, 21375, 256, 21375, 256, 21375, 256, 55362, 56876, - 256, 28784, 256, 21450, 256, 21471, 256, 55362, 57187, 256, 21483, 256, - 21489, 256, 21510, 256, 21662, 256, 21560, 256, 21576, 256, 21608, 256, - 21666, 256, 21750, 256, 21776, 256, 21843, 256, 21859, 256, 21892, 256, - 21892, 256, 21913, 256, 21931, 256, 21939, 256, 21954, 256, 22294, 256, - 22022, 256, 22295, 256, 22097, 256, 22132, 256, 20999, 256, 22766, 256, - 22478, 256, 22516, 256, 22541, 256, 22411, 256, 22578, 256, 22577, 256, - 22700, 256, 55365, 56548, 256, 22770, 256, 22775, 256, 22790, 256, 22810, - 256, 22818, 256, 22882, 256, 55365, 57000, 256, 55365, 57066, 256, 23020, - 256, 23067, 256, 23079, 256, 23000, 256, 23142, 256, 14062, 256, 14076, - 256, 23304, 256, 23358, 256, 23358, 256, 55366, 56776, 256, 23491, 256, - 23512, 256, 23527, 256, 23539, 256, 55366, 57112, 256, 23551, 256, 23558, - 256, 24403, 256, 23586, 256, 14209, 256, 23648, 256, 23662, 256, 23744, - 256, 23693, 256, 55367, 56804, 256, 23875, 256, 55367, 56806, 256, 23918, - 256, 23915, 256, 23932, 256, 24033, 256, 24034, 256, 14383, 256, 24061, - 256, 24104, 256, 24125, 256, 24169, 256, 14434, 256, 55368, 56707, 256, - 14460, 256, 24240, 256, 24243, 256, 24246, 256, 24266, 256, 55400, 57234, - 256, 24318, 256, 55368, 57137, 256, 55368, 57137, 256, 33281, 256, 24354, - 256, 24354, 256, 14535, 256, 55372, 57016, 256, 55384, 56794, 256, 24418, - 256, 24427, 256, 14563, 256, 24474, 256, 24525, 256, 24535, 256, 24569, - 256, 24705, 256, 14650, 256, 14620, 256, 24724, 256, 55369, 57044, 256, - 24775, 256, 24904, 256, 24908, 256, 24910, 256, 24908, 256, 24954, 256, - 24974, 256, 25010, 256, 24996, 256, 25007, 256, 25054, 256, 25074, 256, - 25078, 256, 25104, 256, 25115, 256, 25181, 256, 25265, 256, 25300, 256, - 25424, 256, 55370, 57100, 256, 25405, 256, 25340, 256, 25448, 256, 25475, - 256, 25572, 256, 55370, 57329, 256, 25634, 256, 25541, 256, 25513, 256, - 14894, 256, 25705, 256, 25726, 256, 25757, 256, 25719, 256, 14956, 256, - 25935, 256, 25964, 256, 55372, 56330, 256, 26083, 256, 26360, 256, 26185, - 256, 15129, 256, 26257, 256, 15112, 256, 15076, 256, 20882, 256, 20885, - 256, 26368, 256, 26268, 256, 32941, 256, 17369, 256, 26391, 256, 26395, - 256, 26401, 256, 26462, 256, 26451, 256, 55372, 57283, 256, 15177, 256, - 26618, 256, 26501, 256, 26706, 256, 26757, 256, 55373, 56429, 256, 26766, - 256, 26655, 256, 26900, 256, 15261, 256, 26946, 256, 27043, 256, 27114, - 256, 27304, 256, 55373, 56995, 256, 27355, 256, 15384, 256, 27425, 256, - 55374, 56487, 256, 27476, 256, 15438, 256, 27506, 256, 27551, 256, 27578, - 256, 27579, 256, 55374, 56973, 256, 55367, 56587, 256, 55374, 57082, 256, - 27726, 256, 55375, 56508, 256, 27839, 256, 27853, 256, 27751, 256, 27926, - 256, 27966, 256, 28023, 256, 27969, 256, 28009, 256, 28024, 256, 28037, - 256, 55375, 56606, 256, 27956, 256, 28207, 256, 28270, 256, 15667, 256, - 28363, 256, 28359, 256, 55375, 57041, 256, 28153, 256, 28526, 256, 55375, - 57182, 256, 55375, 57230, 256, 28614, 256, 28729, 256, 28702, 256, 28699, - 256, 15766, 256, 28746, 256, 28797, 256, 28791, 256, 28845, 256, 55361, - 56613, 256, 28997, 256, 55376, 56931, 256, 29084, 256, 55376, 57259, 256, - 29224, 256, 29237, 256, 29264, 256, 55377, 56840, 256, 29312, 256, 29333, - 256, 55377, 57141, 256, 55378, 56340, 256, 29562, 256, 29579, 256, 16044, - 256, 29605, 256, 16056, 256, 16056, 256, 29767, 256, 29788, 256, 29809, - 256, 29829, 256, 29898, 256, 16155, 256, 29988, 256, 55379, 56374, 256, - 30014, 256, 55379, 56466, 256, 30064, 256, 55368, 56735, 256, 30224, 256, - 55379, 57249, 256, 55379, 57272, 256, 55380, 56388, 256, 16380, 256, - 16392, 256, 30452, 256, 55380, 56563, 256, 55380, 56562, 256, 55380, - 56601, 256, 55380, 56627, 256, 30494, 256, 30495, 256, 30495, 256, 30538, - 256, 16441, 256, 30603, 256, 16454, 256, 16534, 256, 55381, 56349, 256, - 30798, 256, 30860, 256, 30924, 256, 16611, 256, 55381, 56870, 256, 31062, - 256, 55381, 56986, 256, 55381, 57029, 256, 31119, 256, 31211, 256, 16687, - 256, 31296, 256, 31306, 256, 31311, 256, 55382, 56700, 256, 55382, 56999, - 256, 55382, 56999, 256, 31470, 256, 16898, 256, 55382, 57259, 256, 31686, - 256, 31689, 256, 16935, 256, 55383, 56448, 256, 31954, 256, 17056, 256, - 31976, 256, 31971, 256, 32000, 256, 55383, 57222, 256, 32099, 256, 17153, - 256, 32199, 256, 32258, 256, 32325, 256, 17204, 256, 55384, 56872, 256, - 55384, 56903, 256, 17241, 256, 55384, 57049, 256, 32634, 256, 55384, - 57150, 256, 32661, 256, 32762, 256, 32773, 256, 55385, 56538, 256, 55385, - 56611, 256, 32864, 256, 55385, 56744, 256, 32880, 256, 55372, 57183, 256, - 17365, 256, 32946, 256, 33027, 256, 17419, 256, 33086, 256, 23221, 256, - 55385, 57255, 256, 55385, 57269, 256, 55372, 57235, 256, 55372, 57244, - 256, 33281, 256, 33284, 256, 36766, 256, 17515, 256, 33425, 256, 33419, - 256, 33437, 256, 21171, 256, 33457, 256, 33459, 256, 33469, 256, 33510, - 256, 55386, 57148, 256, 33509, 256, 33565, 256, 33635, 256, 33709, 256, - 33571, 256, 33725, 256, 33767, 256, 33879, 256, 33619, 256, 33738, 256, - 33740, 256, 33756, 256, 55387, 56374, 256, 55387, 56683, 256, 55387, - 56533, 256, 17707, 256, 34033, 256, 34035, 256, 34070, 256, 55388, 57290, - 256, 34148, 256, 55387, 57132, 256, 17757, 256, 17761, 256, 55387, 57265, - 256, 55388, 56530, 256, 17771, 256, 34384, 256, 34396, 256, 34407, 256, - 34409, 256, 34473, 256, 34440, 256, 34574, 256, 34530, 256, 34681, 256, - 34600, 256, 34667, 256, 34694, 256, 17879, 256, 34785, 256, 34817, 256, - 17913, 256, 34912, 256, 34915, 256, 55389, 56935, 256, 35031, 256, 35038, - 256, 17973, 256, 35066, 256, 13499, 256, 55390, 56494, 256, 55390, 56678, - 256, 18110, 256, 18119, 256, 35488, 256, 35565, 256, 35722, 256, 35925, - 256, 55391, 56488, 256, 36011, 256, 36033, 256, 36123, 256, 36215, 256, - 55391, 57135, 256, 55362, 56324, 256, 36299, 256, 36284, 256, 36336, 256, - 55362, 56542, 256, 36564, 256, 36664, 256, 55393, 56786, 256, 55393, + 21942, 266, 37197, 770, 12308, 26412, 12309, 770, 12308, 19977, 12309, + 770, 12308, 20108, 12309, 770, 12308, 23433, 12309, 770, 12308, 28857, + 12309, 770, 12308, 25171, 12309, 770, 12308, 30423, 12309, 770, 12308, + 21213, 12309, 770, 12308, 25943, 12309, 263, 24471, 263, 21487, 256, + 20029, 256, 20024, 256, 20033, 256, 55360, 56610, 256, 20320, 256, 20398, + 256, 20411, 256, 20482, 256, 20602, 256, 20633, 256, 20711, 256, 20687, + 256, 13470, 256, 55361, 56890, 256, 20813, 256, 20820, 256, 20836, 256, + 20855, 256, 55361, 56604, 256, 13497, 256, 20839, 256, 20877, 256, 55361, + 56651, 256, 20887, 256, 20900, 256, 20172, 256, 20908, 256, 20917, 256, + 55396, 56799, 256, 20981, 256, 20995, 256, 13535, 256, 21051, 256, 21062, + 256, 21106, 256, 21111, 256, 13589, 256, 21191, 256, 21193, 256, 21220, + 256, 21242, 256, 21253, 256, 21254, 256, 21271, 256, 21321, 256, 21329, + 256, 21338, 256, 21363, 256, 21373, 256, 21375, 256, 21375, 256, 21375, + 256, 55362, 56876, 256, 28784, 256, 21450, 256, 21471, 256, 55362, 57187, + 256, 21483, 256, 21489, 256, 21510, 256, 21662, 256, 21560, 256, 21576, + 256, 21608, 256, 21666, 256, 21750, 256, 21776, 256, 21843, 256, 21859, + 256, 21892, 256, 21892, 256, 21913, 256, 21931, 256, 21939, 256, 21954, + 256, 22294, 256, 22022, 256, 22295, 256, 22097, 256, 22132, 256, 20999, + 256, 22766, 256, 22478, 256, 22516, 256, 22541, 256, 22411, 256, 22578, + 256, 22577, 256, 22700, 256, 55365, 56548, 256, 22770, 256, 22775, 256, + 22790, 256, 22810, 256, 22818, 256, 22882, 256, 55365, 57000, 256, 55365, + 57066, 256, 23020, 256, 23067, 256, 23079, 256, 23000, 256, 23142, 256, + 14062, 256, 14076, 256, 23304, 256, 23358, 256, 23358, 256, 55366, 56776, + 256, 23491, 256, 23512, 256, 23527, 256, 23539, 256, 55366, 57112, 256, + 23551, 256, 23558, 256, 24403, 256, 23586, 256, 14209, 256, 23648, 256, + 23662, 256, 23744, 256, 23693, 256, 55367, 56804, 256, 23875, 256, 55367, + 56806, 256, 23918, 256, 23915, 256, 23932, 256, 24033, 256, 24034, 256, + 14383, 256, 24061, 256, 24104, 256, 24125, 256, 24169, 256, 14434, 256, + 55368, 56707, 256, 14460, 256, 24240, 256, 24243, 256, 24246, 256, 24266, + 256, 55400, 57234, 256, 24318, 256, 55368, 57137, 256, 55368, 57137, 256, + 33281, 256, 24354, 256, 24354, 256, 14535, 256, 55372, 57016, 256, 55384, + 56794, 256, 24418, 256, 24427, 256, 14563, 256, 24474, 256, 24525, 256, + 24535, 256, 24569, 256, 24705, 256, 14650, 256, 14620, 256, 24724, 256, + 55369, 57044, 256, 24775, 256, 24904, 256, 24908, 256, 24910, 256, 24908, + 256, 24954, 256, 24974, 256, 25010, 256, 24996, 256, 25007, 256, 25054, + 256, 25074, 256, 25078, 256, 25104, 256, 25115, 256, 25181, 256, 25265, + 256, 25300, 256, 25424, 256, 55370, 57100, 256, 25405, 256, 25340, 256, + 25448, 256, 25475, 256, 25572, 256, 55370, 57329, 256, 25634, 256, 25541, + 256, 25513, 256, 14894, 256, 25705, 256, 25726, 256, 25757, 256, 25719, + 256, 14956, 256, 25935, 256, 25964, 256, 55372, 56330, 256, 26083, 256, + 26360, 256, 26185, 256, 15129, 256, 26257, 256, 15112, 256, 15076, 256, + 20882, 256, 20885, 256, 26368, 256, 26268, 256, 32941, 256, 17369, 256, + 26391, 256, 26395, 256, 26401, 256, 26462, 256, 26451, 256, 55372, 57283, + 256, 15177, 256, 26618, 256, 26501, 256, 26706, 256, 26757, 256, 55373, + 56429, 256, 26766, 256, 26655, 256, 26900, 256, 15261, 256, 26946, 256, + 27043, 256, 27114, 256, 27304, 256, 55373, 56995, 256, 27355, 256, 15384, + 256, 27425, 256, 55374, 56487, 256, 27476, 256, 15438, 256, 27506, 256, + 27551, 256, 27578, 256, 27579, 256, 55374, 56973, 256, 55367, 56587, 256, + 55374, 57082, 256, 27726, 256, 55375, 56508, 256, 27839, 256, 27853, 256, + 27751, 256, 27926, 256, 27966, 256, 28023, 256, 27969, 256, 28009, 256, + 28024, 256, 28037, 256, 55375, 56606, 256, 27956, 256, 28207, 256, 28270, + 256, 15667, 256, 28363, 256, 28359, 256, 55375, 57041, 256, 28153, 256, + 28526, 256, 55375, 57182, 256, 55375, 57230, 256, 28614, 256, 28729, 256, + 28702, 256, 28699, 256, 15766, 256, 28746, 256, 28797, 256, 28791, 256, + 28845, 256, 55361, 56613, 256, 28997, 256, 55376, 56931, 256, 29084, 256, + 55376, 57259, 256, 29224, 256, 29237, 256, 29264, 256, 55377, 56840, 256, + 29312, 256, 29333, 256, 55377, 57141, 256, 55378, 56340, 256, 29562, 256, + 29579, 256, 16044, 256, 29605, 256, 16056, 256, 16056, 256, 29767, 256, + 29788, 256, 29809, 256, 29829, 256, 29898, 256, 16155, 256, 29988, 256, + 55379, 56374, 256, 30014, 256, 55379, 56466, 256, 30064, 256, 55368, + 56735, 256, 30224, 256, 55379, 57249, 256, 55379, 57272, 256, 55380, + 56388, 256, 16380, 256, 16392, 256, 30452, 256, 55380, 56563, 256, 55380, + 56562, 256, 55380, 56601, 256, 55380, 56627, 256, 30494, 256, 30495, 256, + 30495, 256, 30538, 256, 16441, 256, 30603, 256, 16454, 256, 16534, 256, + 55381, 56349, 256, 30798, 256, 30860, 256, 30924, 256, 16611, 256, 55381, + 56870, 256, 31062, 256, 55381, 56986, 256, 55381, 57029, 256, 31119, 256, + 31211, 256, 16687, 256, 31296, 256, 31306, 256, 31311, 256, 55382, 56700, + 256, 55382, 56999, 256, 55382, 56999, 256, 31470, 256, 16898, 256, 55382, + 57259, 256, 31686, 256, 31689, 256, 16935, 256, 55383, 56448, 256, 31954, + 256, 17056, 256, 31976, 256, 31971, 256, 32000, 256, 55383, 57222, 256, + 32099, 256, 17153, 256, 32199, 256, 32258, 256, 32325, 256, 17204, 256, + 55384, 56872, 256, 55384, 56903, 256, 17241, 256, 55384, 57049, 256, + 32634, 256, 55384, 57150, 256, 32661, 256, 32762, 256, 32773, 256, 55385, + 56538, 256, 55385, 56611, 256, 32864, 256, 55385, 56744, 256, 32880, 256, + 55372, 57183, 256, 17365, 256, 32946, 256, 33027, 256, 17419, 256, 33086, + 256, 23221, 256, 55385, 57255, 256, 55385, 57269, 256, 55372, 57235, 256, + 55372, 57244, 256, 33281, 256, 33284, 256, 36766, 256, 17515, 256, 33425, + 256, 33419, 256, 33437, 256, 21171, 256, 33457, 256, 33459, 256, 33469, + 256, 33510, 256, 55386, 57148, 256, 33509, 256, 33565, 256, 33635, 256, + 33709, 256, 33571, 256, 33725, 256, 33767, 256, 33879, 256, 33619, 256, + 33738, 256, 33740, 256, 33756, 256, 55387, 56374, 256, 55387, 56683, 256, + 55387, 56533, 256, 17707, 256, 34033, 256, 34035, 256, 34070, 256, 55388, + 57290, 256, 34148, 256, 55387, 57132, 256, 17757, 256, 17761, 256, 55387, + 57265, 256, 55388, 56530, 256, 17771, 256, 34384, 256, 34396, 256, 34407, + 256, 34409, 256, 34473, 256, 34440, 256, 34574, 256, 34530, 256, 34681, + 256, 34600, 256, 34667, 256, 34694, 256, 17879, 256, 34785, 256, 34817, + 256, 17913, 256, 34912, 256, 34915, 256, 55389, 56935, 256, 35031, 256, + 35038, 256, 17973, 256, 35066, 256, 13499, 256, 55390, 56494, 256, 55390, + 56678, 256, 18110, 256, 18119, 256, 35488, 256, 35565, 256, 35722, 256, + 35925, 256, 55391, 56488, 256, 36011, 256, 36033, 256, 36123, 256, 36215, + 256, 55391, 57135, 256, 55362, 56324, 256, 36299, 256, 36284, 256, 36336, + 256, 55362, 56542, 256, 36564, 256, 36664, 256, 55393, 56786, 256, 55393, 56813, 256, 37012, 256, 37105, 256, 37137, 256, 55393, 57134, 256, 37147, 256, 37432, 256, 37591, 256, 37592, 256, 37500, 256, 37881, 256, 37909, 256, 55394, 57338, 256, 38283, 256, 18837, 256, 38327, 256, 55395, 56695, @@ -4642,64 +5094,64 @@ static const unsigned short decomp_index2[] = { 13103, 13105, 13107, 13109, 13111, 13113, 13115, 13117, 13119, 13121, 13123, 13125, 13127, 13129, 13131, 13133, 13135, 13137, 13139, 13141, 13143, 13145, 13147, 13149, 13151, 13153, 13155, 13157, 13159, 13161, - 13163, 13165, 13167, 13169, 13171, 13173, 13175, 13177, 0, 0, 0, 0, 0, - 13179, 13183, 13187, 13191, 13195, 13199, 13203, 13207, 13211, 0, 0, 0, - 0, 0, 0, 0, 13215, 13217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 13219, 13221, 13223, 13225, 13228, 13230, 13232, 13234, 13236, 13238, - 13240, 13242, 13244, 13246, 13249, 13251, 13253, 13255, 13257, 13260, - 13262, 13264, 13266, 13269, 13271, 13273, 13275, 13277, 13279, 13282, - 13284, 13286, 13288, 13290, 13292, 13294, 13296, 13298, 13300, 13302, - 13304, 13306, 13308, 13310, 13312, 13314, 13316, 13318, 13320, 13322, - 13324, 13326, 13328, 13331, 13333, 13335, 13337, 13340, 13342, 13344, - 13346, 13348, 13350, 13352, 13354, 13356, 13358, 13360, 13362, 13364, - 13366, 13368, 13370, 13372, 13374, 13376, 13378, 13380, 13382, 13384, - 13386, 13388, 13390, 13392, 13394, 13396, 13398, 13400, 13402, 13404, - 13407, 13409, 13411, 13413, 13415, 13417, 13419, 13422, 13425, 13427, - 13429, 13431, 13433, 13435, 13437, 13439, 13441, 13443, 13445, 13448, - 13450, 13452, 13454, 13456, 13459, 13461, 13463, 13465, 13467, 13469, - 13471, 13473, 13475, 13477, 13480, 13482, 13485, 13487, 13489, 13491, - 13493, 13495, 13497, 13499, 13501, 13503, 13505, 13507, 13510, 13512, - 13514, 13516, 13518, 13520, 13523, 13525, 13528, 13531, 13533, 13535, - 13537, 13539, 13542, 13545, 13547, 13549, 13551, 13553, 13555, 13557, - 13559, 13561, 13563, 13565, 13567, 13570, 13572, 13574, 13576, 13578, - 13580, 13582, 13584, 13586, 13588, 13590, 13592, 13594, 13596, 13598, - 13600, 13602, 13604, 13606, 13608, 13611, 13613, 13615, 13617, 13619, - 13621, 13624, 13626, 13628, 13630, 13632, 13634, 13636, 13638, 13640, - 13642, 13644, 13646, 13649, 13651, 13653, 13655, 13657, 13659, 13661, - 13663, 13665, 13667, 13669, 13671, 13673, 13675, 13677, 13679, 13681, - 13683, 13685, 13688, 13690, 13692, 13694, 13696, 13698, 13701, 13703, - 13705, 13707, 13709, 13711, 13713, 13715, 13717, 13720, 13722, 13724, - 13726, 13729, 13731, 13733, 13735, 13737, 13739, 13741, 13744, 13747, - 13750, 13752, 13755, 13757, 13759, 13761, 13763, 13765, 13767, 13769, - 13771, 13773, 13775, 13778, 13780, 13782, 13784, 13786, 13788, 13790, - 13793, 13795, 13797, 13800, 13803, 13805, 13807, 13809, 13811, 13813, - 13815, 13817, 13819, 13821, 13824, 13826, 13829, 13831, 13834, 13836, - 13838, 13840, 13843, 13845, 13847, 13850, 13853, 13855, 13857, 13859, - 13861, 13863, 13865, 13867, 13869, 13871, 13873, 13875, 13877, 13879, - 13882, 13884, 13887, 13889, 13892, 13894, 13897, 13900, 13903, 13905, - 13907, 13909, 13912, 13915, 13918, 13921, 13923, 13925, 13927, 13929, - 13931, 13933, 13935, 13937, 13940, 13942, 13944, 13946, 13948, 13951, - 13953, 13956, 13959, 13961, 13963, 13965, 13967, 13969, 13971, 13974, - 13977, 13980, 13982, 13984, 13987, 13989, 13991, 13993, 13996, 13998, - 14000, 14002, 14004, 14006, 14009, 14011, 14013, 14015, 14017, 14019, - 14021, 14024, 14027, 14029, 14032, 14034, 14037, 14039, 14041, 14043, - 14046, 14049, 14051, 14054, 14056, 14059, 14061, 14063, 14065, 14067, - 14069, 14071, 14074, 14077, 14080, 14083, 14085, 14087, 14089, 14091, - 14093, 14095, 14097, 14099, 14101, 14103, 14105, 14107, 14110, 14112, - 14114, 14116, 14118, 14120, 14122, 14124, 14126, 14128, 14130, 14132, - 14134, 14137, 14140, 14143, 14145, 14147, 14149, 14151, 14154, 14156, - 14159, 14161, 14163, 14166, 14169, 14171, 14173, 14175, 14177, 14179, - 14181, 14183, 14185, 14187, 14189, 14191, 14193, 14195, 14197, 14199, - 14201, 14203, 14205, 14207, 14210, 14212, 14214, 14216, 14218, 14220, - 14223, 14226, 14228, 14230, 14232, 14234, 14236, 14238, 14241, 14243, - 14245, 14247, 14249, 14252, 14255, 14257, 14259, 14261, 14264, 14266, - 14268, 14271, 14274, 14276, 14278, 14280, 14283, 14285, 14287, 14289, - 14291, 14293, 14295, 14297, 14300, 14302, 14304, 14306, 14309, 14311, - 14313, 14315, 14317, 14320, 14323, 14325, 14327, 14329, 14332, 14334, - 14337, 14339, 14341, 14343, 14346, 14348, 14350, 14352, 14354, 14356, - 14358, 14360, 14363, 14365, 14367, 14369, 14371, 14373, 14375, 14378, - 14380, 14383, 14386, 14389, 14391, 14393, 14395, 14397, 14399, 14401, - 14403, 14405, 0, 0, + 13163, 13165, 13167, 13169, 13171, 13173, 13175, 13177, 13179, 0, 0, 0, + 0, 13181, 13185, 13189, 13193, 13197, 13201, 13205, 13209, 13213, 0, 0, + 0, 0, 0, 0, 0, 13217, 13219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13221, 13223, 13225, 13227, 13230, 13232, 13234, 13236, 13238, 13240, + 13242, 13244, 13246, 13248, 13251, 13253, 13255, 13257, 13259, 13262, + 13264, 13266, 13268, 13271, 13273, 13275, 13277, 13279, 13281, 13284, + 13286, 13288, 13290, 13292, 13294, 13296, 13298, 13300, 13302, 13304, + 13306, 13308, 13310, 13312, 13314, 13316, 13318, 13320, 13322, 13324, + 13326, 13328, 13330, 13333, 13335, 13337, 13339, 13342, 13344, 13346, + 13348, 13350, 13352, 13354, 13356, 13358, 13360, 13362, 13364, 13366, + 13368, 13370, 13372, 13374, 13376, 13378, 13380, 13382, 13384, 13386, + 13388, 13390, 13392, 13394, 13396, 13398, 13400, 13402, 13404, 13406, + 13409, 13411, 13413, 13415, 13417, 13419, 13421, 13424, 13427, 13429, + 13431, 13433, 13435, 13437, 13439, 13441, 13443, 13445, 13447, 13450, + 13452, 13454, 13456, 13458, 13461, 13463, 13465, 13467, 13469, 13471, + 13473, 13475, 13477, 13479, 13482, 13484, 13487, 13489, 13491, 13493, + 13495, 13497, 13499, 13501, 13503, 13505, 13507, 13509, 13512, 13514, + 13516, 13518, 13520, 13522, 13525, 13527, 13530, 13533, 13535, 13537, + 13539, 13541, 13544, 13547, 13549, 13551, 13553, 13555, 13557, 13559, + 13561, 13563, 13565, 13567, 13569, 13572, 13574, 13576, 13578, 13580, + 13582, 13584, 13586, 13588, 13590, 13592, 13594, 13596, 13598, 13600, + 13602, 13604, 13606, 13608, 13610, 13613, 13615, 13617, 13619, 13621, + 13623, 13626, 13628, 13630, 13632, 13634, 13636, 13638, 13640, 13642, + 13644, 13646, 13648, 13651, 13653, 13655, 13657, 13659, 13661, 13663, + 13665, 13667, 13669, 13671, 13673, 13675, 13677, 13679, 13681, 13683, + 13685, 13687, 13690, 13692, 13694, 13696, 13698, 13700, 13703, 13705, + 13707, 13709, 13711, 13713, 13715, 13717, 13719, 13722, 13724, 13726, + 13728, 13731, 13733, 13735, 13737, 13739, 13741, 13743, 13746, 13749, + 13752, 13754, 13757, 13759, 13761, 13763, 13765, 13767, 13769, 13771, + 13773, 13775, 13777, 13780, 13782, 13784, 13786, 13788, 13790, 13792, + 13795, 13797, 13799, 13802, 13805, 13807, 13809, 13811, 13813, 13815, + 13817, 13819, 13821, 13823, 13826, 13828, 13831, 13833, 13836, 13838, + 13840, 13842, 13845, 13847, 13849, 13852, 13855, 13857, 13859, 13861, + 13863, 13865, 13867, 13869, 13871, 13873, 13875, 13877, 13879, 13881, + 13884, 13886, 13889, 13891, 13894, 13896, 13899, 13902, 13905, 13907, + 13909, 13911, 13914, 13917, 13920, 13923, 13925, 13927, 13929, 13931, + 13933, 13935, 13937, 13939, 13942, 13944, 13946, 13948, 13950, 13953, + 13955, 13958, 13961, 13963, 13965, 13967, 13969, 13971, 13973, 13976, + 13979, 13982, 13984, 13986, 13989, 13991, 13993, 13995, 13998, 14000, + 14002, 14004, 14006, 14008, 14011, 14013, 14015, 14017, 14019, 14021, + 14023, 14026, 14029, 14031, 14034, 14036, 14039, 14041, 14043, 14045, + 14048, 14051, 14053, 14056, 14058, 14061, 14063, 14065, 14067, 14069, + 14071, 14073, 14076, 14079, 14082, 14085, 14087, 14089, 14091, 14093, + 14095, 14097, 14099, 14101, 14103, 14105, 14107, 14109, 14112, 14114, + 14116, 14118, 14120, 14122, 14124, 14126, 14128, 14130, 14132, 14134, + 14136, 14139, 14142, 14145, 14147, 14149, 14151, 14153, 14156, 14158, + 14161, 14163, 14165, 14168, 14171, 14173, 14175, 14177, 14179, 14181, + 14183, 14185, 14187, 14189, 14191, 14193, 14195, 14197, 14199, 14201, + 14203, 14205, 14207, 14209, 14212, 14214, 14216, 14218, 14220, 14222, + 14225, 14228, 14230, 14232, 14234, 14236, 14238, 14240, 14243, 14245, + 14247, 14249, 14251, 14254, 14257, 14259, 14261, 14263, 14266, 14268, + 14270, 14273, 14276, 14278, 14280, 14282, 14285, 14287, 14289, 14291, + 14293, 14295, 14297, 14299, 14302, 14304, 14306, 14308, 14311, 14313, + 14315, 14317, 14319, 14322, 14325, 14327, 14329, 14331, 14334, 14336, + 14339, 14341, 14343, 14345, 14348, 14350, 14352, 14354, 14356, 14358, + 14360, 14362, 14365, 14367, 14369, 14371, 14373, 14375, 14377, 14380, + 14382, 14385, 14388, 14391, 14393, 14395, 14397, 14399, 14401, 14403, + 14405, 14407, 0, 0, }; /* NFC pairs */ From a732e00ea4fffebaa85a89420f09df4c11d650e0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 21 Jul 2016 01:58:00 -0700 Subject: [PATCH 0020/1326] 1.3.0 --- NEWS | 15 +++++++++++++++ configure.ac | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e62b1989c..6f46119c8 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,18 @@ +Overview of changes leading to 1.3.0 +Thursday, July 21, 2016 +==================================== + +- Update to Unicode 9.0.0 +- Move Javanese from Indic shaper to Universal Shaping Engine. +- Allow MultipleSubst to delete a glyph (matching Windows engine). +- Update Universal Shaping Engine to latest draft from Microsoft. +- DirectWrite backend improvements. Note: this backend is for testing ONLY. +- CoreText backend improvements with unreachable fonts. +- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font. +- Blacklist bad GDEF of more fonts (Tahoma & others). +- Misc fixes. + + Overview of changes leading to 1.2.7 Monday, May 2, 2016 ==================================== diff --git a/configure.ac b/configure.ac index 740beb896..e1a28f2d8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.2.7], + [1.3.0], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 489acf6c3180d3726158864fa0e1adeea3c23fae Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 22 Jul 2016 17:41:43 -0700 Subject: [PATCH 0021/1326] [coretext] "Fix" crashes on CoreText < 10.10 Fixes https://github.com/behdad/harfbuzz/issues/297 --- src/hb-coretext.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index f4d9716e9..c50537341 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -145,6 +145,14 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); return NULL; } + + /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter + * bug indicate that the cascade list reconfiguration occasionally causes + * crashes in CoreText on OS X 10.9, thus let's skip this step on older + * operating system versions. */ + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber10_10) + return ct_font; + CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute); /* Create font copy with cascade list that has LastResort first; this speeds up CoreText From dd31fc9f7e6d23b414b22874de96eb3c002c80ba Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 22 Jul 2016 02:26:54 +0300 Subject: [PATCH 0022/1326] =?UTF-8?q?Don=E2=80=99t=20build=20UCDN=20suppor?= =?UTF-8?q?t=20when=20building=20with=20GLib=20(#296)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression from: b424b6c372dfe4c0ed75a49761eb34a416819446. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e1a28f2d8..e572d98c9 100644 --- a/configure.ac +++ b/configure.ac @@ -288,7 +288,7 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin") dnl =========================================================================== have_ucdn=true -if $have_glib || $have_icu && test "x$with_icu" = "xbuiltin"; then +if $have_glib || test \( $have_icu -a "x$with_icu" = "xbuiltin" \); then have_ucdn=false fi if $have_ucdn; then From 10a0d4aa2254f783758bb908175047df3a0b41fe Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 16:51:08 -0700 Subject: [PATCH 0023/1326] Map zh-Hant-HK to ZHH Fixes https://github.com/behdad/harfbuzz/issues/300 --- src/hb-ot-tag.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 04835576d..fdebb05c2 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -826,16 +826,18 @@ static const LangTag ot_languages[] = { }; typedef struct { - char language[8]; + char language[11]; hb_tag_t tag; } LangTagLong; static const LangTagLong ot_languages_zh[] = { + /* Store longest-first, if one is a prefix of another. */ {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */ {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */ {"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */ + {"zh-hant-hk",HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ {"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */ }; From 333173103bb618f721bd25d0c565a3c3c9ea224e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 17:24:04 -0700 Subject: [PATCH 0024/1326] Fix sign of shift operators This one: map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); before the fix, the shift was done as an int, causing overflow if it ever got to 1 << 31. Sprinkle 'u's around. Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=634805 --- src/hb-buffer-private.hh | 6 +++--- src/hb-cache-private.hh | 8 ++++---- src/hb-coretext.cc | 2 +- src/hb-directwrite.cc | 2 +- src/hb-face.cc | 2 -- src/hb-font.cc | 2 -- src/hb-ft.cc | 6 ++++-- src/hb-ot-map.cc | 4 ++-- src/hb-set-private.hh | 4 ++-- src/hb-uniscribe.cc | 4 ++-- 10 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh index ed592f448..bca308da2 100644 --- a/src/hb-buffer-private.hh +++ b/src/hb-buffer-private.hh @@ -134,7 +134,7 @@ struct hb_buffer_t { #ifndef HB_NDEBUG unsigned int end = start + count; assert (end <= 8); - unsigned int bits = (1<> value_bits) != (key >> cache_bits)) return false; - *value = v & ((1<> key_bits) || (value >> value_bits))) return false; /* Overflows */ - unsigned int k = key & ((1<>cache_bits)< hb_cmap_cache_t; diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index c50537341..3e56f15b1 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -725,7 +725,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, pchars[chars_len++] = 0xFFFDu; else { pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); - pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); } } diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 09889d04e..6846a86c6 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -586,7 +586,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, textString[chars_len++] = 0xFFFDu; else { textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); - textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); } } diff --git a/src/hb-face.cc b/src/hb-face.cc index 9effc41c8..6b563bc8f 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -35,8 +35,6 @@ #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" -#include "hb-cache-private.hh" - #include diff --git a/src/hb-font.cc b/src/hb-font.cc index 60554b9c7..08fcd6475 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -35,8 +35,6 @@ #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" -#include "hb-cache-private.hh" - #include diff --git a/src/hb-ft.cc b/src/hb-ft.cc index eaa1311d4..2b06c59be 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -33,6 +33,8 @@ #include "hb-font-private.hh" +#include "hb-cache-private.hh" // Maybe use in the future? + #include FT_ADVANCES_H #include FT_TRUETYPE_TABLES_H @@ -606,8 +608,8 @@ hb_ft_font_create (FT_Face ft_face, hb_face_destroy (face); _hb_ft_font_set_funcs (font, ft_face, false); hb_font_set_scale (font, - (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), - (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); + (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16), + (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16)); #if 0 /* hb-ft works in no-hinting model */ hb_font_set_ppem (font, ft_face->size->metrics.x_ppem, diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 7822cef8b..35550af34 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -243,11 +243,11 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) map->mask = 1; } else { map->shift = next_bit; - map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); + map->mask = (1u << (next_bit + bits_needed)) - (1u << next_bit); next_bit += bits_needed; m.global_mask |= (info->default_value << map->shift) & map->mask; } - map->_1_mask = (1 << map->shift) & map->mask; + map->_1_mask = (1u << map->shift) & map->mask; map->needs_fallback = !found; } diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh index 3c302b1da..e2010d762 100644 --- a/src/hb-set-private.hh +++ b/src/hb-set-private.hh @@ -313,7 +313,7 @@ struct hb_set_t for (unsigned int i = 0; i < ELTS; i++) if (elts[i]) for (unsigned int j = 0; j < BITS; j++) - if (elts[i] & (1 << j)) + if (elts[i] & (1u << j)) return i * BITS + j; return INVALID; } @@ -322,7 +322,7 @@ struct hb_set_t for (unsigned int i = ELTS; i; i--) if (elts[i - 1]) for (unsigned int j = BITS; j; j--) - if (elts[i - 1] & (1 << (j - 1))) + if (elts[i - 1] & (1u << (j - 1))) return (i - 1) * BITS + (j - 1); return INVALID; } diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 7fda6788b..07007a640 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -771,7 +771,7 @@ retry: pchars[chars_len++] = 0xFFFDu; else { pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); - pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); + pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); } } @@ -827,7 +827,7 @@ retry: /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ //bidi_control.fMergeNeutralItems = true; - *(uint32_t*)&bidi_control |= 1<<24; + *(uint32_t*)&bidi_control |= 1u<<24; bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; bidi_state.fOverrideDirection = 1; From 09c7a2d6bf00dc902343e999f92cac0e8146f949 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 17:28:54 -0700 Subject: [PATCH 0025/1326] Limit bits-per-feature to eight Limits number of alternatives per glyph per feature to 255, so be it. That's better than possibly breaking shaping because of one bad feature value. --- src/hb-ot-map.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 35550af34..17e3f4065 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -193,7 +193,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) /* Uses the global bit */ bits_needed = 0; else - bits_needed = _hb_bit_storage (info->max_value); + /* Limit to 8 bits per feature. */ + bits_needed = MIN(8u, _hb_bit_storage (info->max_value)); if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) continue; /* Feature disabled, or not enough bits. */ From 37f21bdbb75c98d741e749b7f1e0f367941aef4e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 17:57:06 -0700 Subject: [PATCH 0026/1326] Map Macao to ZHH lang tag Fixes https://github.com/behdad/harfbuzz/issues/300 --- src/hb-ot-tag.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index fdebb05c2..34d7b37c1 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -833,11 +833,12 @@ static const LangTagLong ot_languages_zh[] = { /* Store longest-first, if one is a prefix of another. */ {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ - {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */ + {"zh-mo", HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ {"zh-tw", HB_TAG('Z','H','T',' ')}, /* Chinese (Taiwan) */ {"zh-hans", HB_TAG('Z','H','S',' ')}, /* Chinese (Simplified) */ {"zh-hant-hk",HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ + {"zh-hant-mo",HB_TAG('Z','H','H',' ')}, /* Chinese (Macao) */ {"zh-hant", HB_TAG('Z','H','T',' ')}, /* Chinese (Traditional) */ }; From f1b76275da716a4174092e6389979e03c0e3be59 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 18:06:09 -0700 Subject: [PATCH 0027/1326] Add tests for Chinese language tags Using font from https://github.com/behdad/harfbuzz/issues/300 --- .../6991b13ce889466be6de3f66e891de2bc0f117ee.ttf | Bin 0 -> 5596 bytes test/shaping/tests/language-tags.tests | 12 ++++++++++++ 2 files changed, 12 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf create mode 100644 test/shaping/tests/language-tags.tests diff --git a/test/shaping/fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf b/test/shaping/fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d98496683c503a9ee00806af6ed47c4c06d7674b GIT binary patch literal 5596 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 WffzAF8om)y+ZlL|V#Fr_m;5)%n?nl# literal 0 HcmV?d00001 diff --git a/test/shaping/tests/language-tags.tests b/test/shaping/tests/language-tags.tests new file mode 100644 index 000000000..17adafaa2 --- /dev/null +++ b/test/shaping/tests/language-tags.tests @@ -0,0 +1,12 @@ +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=fa:U+004A:[gid2=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=ja:U+004A:[gid2=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh:U+004A:[gid4=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-cn:U+004A:[gid4=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-sg:U+004A:[gid4=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-tw:U+004A:[gid5=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-hans:U+004A:[gid4=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-hant:U+004A:[gid5=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-hant-hk:U+004A:[gid6=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-HK:U+004A:[gid6=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-mo:U+004A:[gid6=0+1000] +fonts/sha1sum/6991b13ce889466be6de3f66e891de2bc0f117ee.ttf:--language=zh-Hant-mo:U+004A:[gid6=0+1000] From 91f2585411aaf5565fcf0c991b9055b0b397f1cd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Aug 2016 18:08:08 -0700 Subject: [PATCH 0028/1326] Actually add test --- test/shaping/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index e67e3ef6c..c5efe6251 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -54,6 +54,7 @@ TESTS = \ tests/indic-joiner-candrabindu.tests \ tests/indic-old-spec.tests \ tests/indic-pref-blocking.tests \ + tests/language-tags.tests \ tests/ligature-id.tests \ tests/mark-filtering-sets.tests \ tests/mongolian-variation-selector.tests \ From 18c19dd34dcdcaab0a6d47768339f8fb70c0d3f0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 9 Aug 2016 13:03:14 -0700 Subject: [PATCH 0029/1326] Fix build --- test/api/test-ot-tag.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c index 29e0aa225..eda87ff8c 100644 --- a/test/api/test-ot-tag.c +++ b/test/api/test-ot-tag.c @@ -198,7 +198,10 @@ test_ot_tag_language (void) test_tag_from_language ("ZHS", "zh"); /* Chinese */ test_tag_from_language ("ZHS", "zh-cn"); /* Chinese (China) */ test_tag_from_language ("ZHS", "zh-sg"); /* Chinese (Singapore) */ - test_tag_from_language ("ZHT", "zh-mo"); /* Chinese (Macao) */ + test_tag_from_language ("ZHH", "zh-mo"); /* Chinese (Macao) */ + test_tag_from_language ("ZHH", "zh-hant-mo"); /* Chinese (Macao) */ + test_tag_from_language ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */ + test_tag_from_language ("ZHH", "zH-HanT-hK"); /* Chinese (Hong Kong) */ test_tag_from_language ("ZHT", "zh-tw"); /* Chinese (Taiwan) */ test_tag_from_language ("ZHS", "zh-Hans"); /* Chinese (Simplified) */ test_tag_from_language ("ZHT", "zh-Hant"); /* Chinese (Traditional) */ From 0634d5600e559a69a92d49173ffb8e715fe7576c Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Tue, 16 Aug 2016 02:49:48 +0200 Subject: [PATCH 0030/1326] [travis] Fix MacOS libtool issue Reveals another MacOS build breakage in the Core Text shaper. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f37b4b228..1b150584e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then pip install --user cpp-coveralls; fi # for coveralls.io code coverage tracking - if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PATH=$HOME/.local/bin:$PATH; fi # Make sure we can find the above Python packages - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi; + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew uninstall libtool && brew install libtool; fi # Workaround Travis/brew bug - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ragel freetype glib gobject-introspection cairo icu4c graphite2; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew link --force icu4c; fi # icu4c is keg-only script: From a0f1b44b6c0e3b1e6a1ba63dde2be22e0425353f Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Tue, 16 Aug 2016 03:09:04 +0200 Subject: [PATCH 0031/1326] [coretext] Blind fix for build on MacOS 10.9 --- src/hb-coretext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 3e56f15b1..9e24e9063 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -150,7 +150,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * bug indicate that the cascade list reconfiguration occasionally causes * crashes in CoreText on OS X 10.9, thus let's skip this step on older * operating system versions. */ - if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber10_10) + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() <= kCTVersionNumber10_9) return ct_font; CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute); From e7ecbba2cc3c9369c5e7dc7296cb210018aca3bb Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Thu, 18 Aug 2016 12:48:38 +0200 Subject: [PATCH 0032/1326] Support Americanist Phonetic Notation OpenType language system tag: `APPH` https://www.microsoft.com/typography/otspec/languagetags.htm IETF BCP47 variant tag: `fonnapa` http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry --- src/hb-ot-tag.cc | 14 ++++++++++++-- test/api/test-ot-tag.c | 6 ++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 34d7b37c1..5f21ac096 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -892,13 +892,21 @@ hb_ot_tag_from_language (hb_language_t language) } /* - * The International Phonetic Alphabet is a variant tag in BCP-47, - * which can be applied to any language. + * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet. + * It can be applied to any language. */ if (strstr (lang_str, "-fonipa")) { return HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */ } + /* + * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet + * also known as Americanist Phonetic Notation. It can be applied to any language. + */ + if (strstr (lang_str, "-fonnapa")) { + return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */ + } + /* Find a language matching in the first component */ { const LangTag *lang_tag; @@ -970,6 +978,8 @@ hb_ot_tag_to_language (hb_tag_t tag) /* struct LangTag has only room for 3-letter language tags. */ switch (tag) { + case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ + return hb_language_from_string ("und-fonnapa", -1); case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ return hb_language_from_string ("und-fonipa", -1); } diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c index eda87ff8c..e54e55269 100644 --- a/test/api/test-ot-tag.c +++ b/test/api/test-ot-tag.c @@ -232,6 +232,12 @@ test_ot_tag_language (void) test_tag_from_language ("IPPH", "zh-fonipa"); test_tag_to_language ("IPPH", "und-fonipa"); + /* North American Phonetic Alphabet (Americanist Phonetic Notation) */ + test_tag_from_language ("APPH", "en-fonnapa"); + test_tag_from_language ("APPH", "chr-fonnapa"); + test_tag_from_language ("APPH", "und-fonnapa"); + test_tag_to_language ("APPH", "und-fonnapa"); + /* Test that x-hbot overrides the base language */ test_tag_from_language ("ABC", "fa-x-hbotabc-zxc"); test_tag_from_language ("ABC", "fa-ir-x-hbotabc-zxc"); From 3d976d20f1b97c771e64a9cfed2760ebec64037a Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 27 Aug 2016 16:38:42 +0300 Subject: [PATCH 0033/1326] Show the shaper name in the debug message (#306) --- src/hb-shape-plan.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 56e2ea5c1..87231fb33 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -289,9 +289,10 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, unsigned int num_features) { DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d shaper_func=%p", + "num_features=%d shaper_func=%p, shaper_name=%s", num_features, - shape_plan->shaper_func); + shape_plan->shaper_func, + shape_plan->shaper_name); if (unlikely (!buffer->len)) return true; From c4f36b04e32ae5111ef11d225e5d6e82c8216185 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 1 Sep 2016 17:31:16 +0430 Subject: [PATCH 0034/1326] [ci] Add Windows CI support, provided by AppVeyor (#308) --- README | 1 + appveyor.yml | 28 ++++++++++++++++++++++++++++ win32/generate-msvc.mak | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 appveyor.yml diff --git a/README b/README index 3fcdfb4c3..69a1bdd9f 100644 --- a/README +++ b/README @@ -1,4 +1,5 @@ [![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz) +[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz) [![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz) [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/) diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..391fdc2d8 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,28 @@ +platform: x64 + +environment: + matrix: + - compiler: msvc + ARCH: amd64 + CFG: release + - compiler: msvc + ARCH: x86 + CFG: release + - compiler: msvc + ARCH: amd64 + CFG: debug + - compiler: msvc + ARCH: x86 + CFG: debug + +install: + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" + +build_script: + - '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' + - C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir" + - cd harfbuzz-*\win32 + - nmake /f Makefile.vc CFG=%CFG% DIRECTWRITE=1 + +# disable automatic tests +test: off diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak index 48bd9f0fc..7c17a9465 100644 --- a/win32/generate-msvc.mak +++ b/win32/generate-msvc.mak @@ -23,4 +23,4 @@ $(HB_GOBJECT_ENUM_GENERATED_SOURCES): ..\src\hb-gobject-enums.h.tmpl ..\src\hb-g # Create the build directories $(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-icu $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util: - @-mkdir $@ + @-mkdir -p $@ From 5362ce6a6455c539d615e7fb221a904ac744b74c Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 1 Sep 2016 20:05:45 +0430 Subject: [PATCH 0035/1326] [dwrite] Minor, don't include unnecessary headers (#309) --- src/hb-directwrite.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 6846a86c6..76482acd3 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -29,10 +29,6 @@ #include "hb-directwrite.h" -#include "hb-open-file-private.hh" -#include "hb-ot-name-table.hh" -#include "hb-ot-tag.h" - #ifndef HB_DEBUG_DIRECTWRITE #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) From 17f0dd2dfb9a15aed9d1a229115940cc23bdbc97 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 2 Sep 2016 01:21:48 +0430 Subject: [PATCH 0036/1326] [ci] Add msys2 build to CI and run its testsuite on Windows (#310) --- appveyor.yml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 391fdc2d8..4677a2774 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,14 +15,26 @@ environment: ARCH: x86 CFG: debug + - compiler: msys2 + MINGW_PREFIX: /c/msys2/mingw64/ + MINGW_CHOST: x86_64-w64-mingw32 + MSYS2_ARCH: x86_64 + - compiler: msys2 + MINGW_PREFIX: /c/msys2/mingw32/ + MINGW_CHOST: i686-w64-mingw32 + MSYS2_ARCH: i686 + install: - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" build_script: - - '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' - - C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir" - - cd harfbuzz-*\win32 - - nmake /f Makefile.vc CFG=%CFG% DIRECTWRITE=1 + - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' + - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' + - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% DIRECTWRITE=1' + + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"' # disable automatic tests test: off From 67e9fdf427e8536f0a134f84ad3bf1740245fe12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Mon, 5 Sep 2016 11:27:25 +0300 Subject: [PATCH 0037/1326] Blacklist Padauk 2.80 and 3.00 (#311) According to comments in issue #305 broken GDEF tables lead to incorrect rendering of Latin characters. Blacklisting this font. --- src/hb-ot-layout.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index b52c5f37e..5cb1491c3 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -120,6 +120,14 @@ _hb_ot_layout_create (hb_face_t *face) /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) + /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ + || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) + /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ + || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len) + /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ + || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) + /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ + || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) ) { /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks From b717cd7be506217e466e32a456df9af4d2720c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Wed, 7 Sep 2016 23:56:57 +0300 Subject: [PATCH 0038/1326] Do reconfigure the cascade list for Emoji font on OS X 10.9.5 (#313) This seems to fix crash issues on 10.9.5 reported on Chrome, compare crbug.com/549610 --- src/hb-coretext.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 9e24e9063..ee7f91cc9 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -149,9 +149,16 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter * bug indicate that the cascade list reconfiguration occasionally causes * crashes in CoreText on OS X 10.9, thus let's skip this step on older - * operating system versions. */ - if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() <= kCTVersionNumber10_9) - return ct_font; + * operating system versions. Except for the emoji font, where _not_ + * reconfiguring the cascade list causes CoreText crashes. For details, see + * crbug.com/549610 */ + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber10_10) { + CFStringRef fontName = CTFontCopyPostScriptName (ct_font); + bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; + CFRelease (fontName); + if (!isEmojiFont) + return ct_font; + } CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute); From d22ab6cf040467e7f17476ccdfe9cab4dce16639 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 7 Sep 2016 14:28:47 -0700 Subject: [PATCH 0039/1326] 1.3.1 --- NEWS | 9 +++++++++ configure.ac | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 6f46119c8..52686870c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Overview of changes leading to 1.3.1 +Wednesday, September 7, 2016 +==================================== + +- Blacklist bad GDEF of more fonts (Padauk). +- More CoreText backend crash fixes with OS X 10.9.5. +- Misc fixes. + + Overview of changes leading to 1.3.0 Thursday, July 21, 2016 ==================================== diff --git a/configure.ac b/configure.ac index e572d98c9..ea6fc27cb 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.3.0], + [1.3.1], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 48677345281a93d8829dd37d0480a6062945416a Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Thu, 8 Sep 2016 04:44:37 +0300 Subject: [PATCH 0040/1326] Try to unbreak building on older macOS again (#314) --- src/hb-coretext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index ee7f91cc9..e68ee9113 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -152,7 +152,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * operating system versions. Except for the emoji font, where _not_ * reconfiguring the cascade list causes CoreText crashes. For details, see * crbug.com/549610 */ - if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber10_10) { + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() <= kCTVersionNumber10_9) { CFStringRef fontName = CTFontCopyPostScriptName (ct_font); bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; CFRelease (fontName); From fc4e671f311241e21c1cc3ed941b1fc651875a2e Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 9 Sep 2016 23:28:28 +0430 Subject: [PATCH 0041/1326] [coretext] Use intended coretext version check logic (#315) --- src/hb-coretext.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index e68ee9113..507581bd7 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -152,7 +152,8 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * operating system versions. Except for the emoji font, where _not_ * reconfiguring the cascade list causes CoreText crashes. For details, see * crbug.com/549610 */ - if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() <= kCTVersionNumber10_9) { + // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h + if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) { CFStringRef fontName = CTFontCopyPostScriptName (ct_font); bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; CFRelease (fontName); From 02bfd965af588640250c47f344ad3096c8a373e0 Mon Sep 17 00:00:00 2001 From: Gregory Morse Date: Mon, 12 Sep 2016 10:22:15 +0200 Subject: [PATCH 0042/1326] Update detectenv-msvc.mak (#316) Windows x86 ARM capability --- win32/detectenv-msvc.mak | 3 +++ 1 file changed, 3 insertions(+) diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak index a94ab8471..83d87862c 100644 --- a/win32/detectenv-msvc.mak +++ b/win32/detectenv-msvc.mak @@ -119,6 +119,9 @@ CFLAGS_ADD = /MDd /Od !if "$(PLAT)" == "x64" LDFLAGS_ARCH = /machine:x64 +!elseif "$(PLAT)" == "arm" +LDFLAGS_ARCH = /machine:arm +CFLAGS_ADD = $(CFLAGS_ADD) /DWINAPI_FAMILY=3 !else LDFLAGS_ARCH = /machine:x86 !endif From 5fbcb992bd7887f95b1cf2ca045c9226de8148fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 10:47:15 +0200 Subject: [PATCH 0043/1326] MATH Table: Add API to check availability of math data. --- src/Makefile.sources | 1 + src/hb-ot-layout-math-table.hh | 60 ++++++++++++++++ src/hb-ot-layout-private.hh | 3 + src/hb-ot-layout.cc | 45 ++++++++++++ src/hb-ot-layout.h | 7 ++ test/api/Makefile.am | 14 +++- test/api/fonts/MathTestFontEmpty.otf | Bin 0 -> 14320 bytes test/api/fonts/MathTestFontNone.otf | Bin 0 -> 14284 bytes test/api/test-ot-layout-math.c | 98 +++++++++++++++++++++++++++ 9 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/hb-ot-layout-math-table.hh create mode 100644 test/api/fonts/MathTestFontEmpty.otf create mode 100644 test/api/fonts/MathTestFontNone.otf create mode 100644 test/api/test-ot-layout-math.c diff --git a/src/Makefile.sources b/src/Makefile.sources index ac806838c..cd30b12f0 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -75,6 +75,7 @@ HB_OT_sources = \ hb-ot-layout-gsubgpos-private.hh \ hb-ot-layout-gsub-table.hh \ hb-ot-layout-jstf-table.hh \ + hb-ot-layout-math-table.hh \ hb-ot-layout-private.hh \ hb-ot-map.cc \ hb-ot-map-private.hh \ diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh new file mode 100644 index 000000000..f4ecf3f0e --- /dev/null +++ b/src/hb-ot-layout-math-table.hh @@ -0,0 +1,60 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#ifndef HB_OT_LAYOUT_MATH_TABLE_HH +#define HB_OT_LAYOUT_MATH_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" + +namespace OT { + +/* + * MATH -- The MATH Table + */ + +struct MATH +{ + static const hb_tag_t tableTag = HB_OT_TAG_MATH; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1)); + } + +protected: + FixedVersion<>version; /* Version of the MATH table + initially set to 0x00010000u */ +public: + DEFINE_SIZE_STATIC (4); +}; + +} /* mathspace OT */ + + +#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 778b2c442..a4272de63 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -124,6 +124,7 @@ namespace OT { struct GDEF; struct GSUB; struct GPOS; + struct MATH; } struct hb_ot_layout_lookup_accelerator_t @@ -152,10 +153,12 @@ struct hb_ot_layout_t hb_blob_t *gdef_blob; hb_blob_t *gsub_blob; hb_blob_t *gpos_blob; + hb_blob_t *math_blob; const struct OT::GDEF *gdef; const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; + const struct OT::MATH *math; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5cb1491c3..24d290c5c 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -35,6 +35,7 @@ #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-jstf-table.hh" +#include "hb-ot-layout-math-table.hh" #include "hb-ot-map-private.hh" @@ -60,6 +61,10 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); + // The MATH table is rarer so we only try and load it in _get_math + layout->math_blob = NULL; + layout->math = NULL; + { /* * The ugly business of blacklisting individual fonts' tables happen here! @@ -178,6 +183,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); + if (layout->math_blob) hb_blob_destroy (layout->math_blob); + free (layout); } @@ -199,6 +206,21 @@ _get_gpos (hb_face_t *face) if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS); return *hb_ot_layout_from_face (face)->gpos; } +static inline const OT::MATH& +_get_math (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); + + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + + // If the MATH table is not loaded yet, do it now. + if (!layout->math_blob) { + layout->math_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); + layout->math = OT::Sanitizer::lock_instance (layout->math_blob); + } + + return *layout->math; +} /* @@ -1190,3 +1212,26 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, { apply_string (c, lookup, accel); } + +/* + * OT::MATH + */ + +/** + * hb_ot_layout_has_math_data: + * + * @face: #hb_face_t to test + * + * This function allows to verify the presence of an OpenType MATH table on the + * face. If so, such a table will be loaded into memory and sanitized. You can + * then safely call other functions for math layout and shaping. + * + * Return value: #TRUE if face has a MATH table and #FALSE otherwise + * + * Since: ???? + **/ +hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face) +{ + return &_get_math (face) != &OT::Null(OT::MATH); +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index eb23d45b6..7cbd794ce 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -42,6 +42,7 @@ HB_BEGIN_DECLS #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') +#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') /* @@ -297,6 +298,12 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_end /* OUT. May be NULL */); +/* + * MATH + */ + +HB_EXTERN hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face); HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index d7d40af39..dae8700c3 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -43,10 +43,22 @@ endif if HAVE_OT + TEST_PROGS += \ test-ot-tag \ $(NULL) -endif + +if HAVE_FREETYPE +TEST_PROGS += \ + test-ot-layout-math \ + $(NULL) +test_ot_layout_math_LDADD = $(LDADD) +test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) +test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS) +test_ot_layout_math_LDADD += $(FREETYPE_LIBS) +endif # HAVE_FREETYPE + +endif # HAVE_OT # Tests for header compilation TEST_PROGS += \ diff --git a/test/api/fonts/MathTestFontEmpty.otf b/test/api/fonts/MathTestFontEmpty.otf new file mode 100644 index 0000000000000000000000000000000000000000..6b50d66fc3d653da18010d8c116e3a7778dda109 GIT binary patch literal 14320 zcmds8&5tALS$}(acCu79vzb*uE3&|=21V0~+w-|I(j*5w{+PDbZF_C^Oy+<>wOwvk z#;$Uz%H7iv2P6a%3I{mw4UCAQ?e1kc zL}GeuSG^z4_w#$6x7^(s3_8kDf2_8Zt~MI_AJl*Tmr@V!E2aMSpfcE3TewmW{}pde zr+@42d;juvN2#r^@9z}3U;f5-LD z@cO;UEP1*83tXv(e7`nxU(VH)E-ts;=6&GKyuYs9+{67`sr%obhjH@e&(uAv{|4r@ zkp=R6@=xtQ{r<2^F`rm) zV;gTmWlP<_om^j0U%By(^!jRU{95k%y86u<--Oq;u0o!jYd1bjuea3Bz3-&gSJd@; ze~?~Z&5ggMe*4~wbo^Rw{JOe-@6W5@{4Da1CyBl}+|_q)-+55d&0}}!ySiU)mG#X@ zlFT37y5*a(@-Up;+I5`4#E*3&3=-WB$H}Q1c^U&#f9M6VH`0q>CW5> zWN}Ltl=M?Civ2LqcglClLM+`&GQ)80gUFFL4Nptj4MrSvr*Wv=6W5=*M^jIq`pHDQ zx>5O9yU8Ob6*3-1{yd4xu|F+`(ebTLqvbfx-k1O982P*Pwr+IV1Kny?>+OC$FTUQ> zcOU46cN8t$=nMwD{qX<9(CPN-m4nBvI?Uqf;}Cl5aBOUO&W`#f6x`LceiG_9@n?&v zo4`0>G##D#BhMLmC$Qpt=D|~-G7P6MUl_TGf8yye{Wp)oA9%wgE*TPw`8IcUQAFPKUKASB9Kk+>fqt_r4sGmR%cxoJZ_y|T$ z$Y>ZxNPdX
  • R}o%q9vktWtN_Y98L@dQeZ#P>52!3|c<-6#nVIun2Hm-_&_ITbB`gGT3w70c|TnEk!QjW@ssj_ zCoty1pB5)F?9ihSQj?iGpHI&mtThGQf@EUPWXRZ`g8x!Waj;&3q_YpVd(q8!cb)7s;1KqS5H~Y7 zdcnAgb-Wl(Xbvce=yoJBz%X1yLx@j?B?N+xcuMh$(Fj9`$|nDy%1$r!tUzfS?#=5! zD~ZeFxi?IMT9|8hoCq8{fYuc4;{-@SlR_6#@1O|yfjhO>mZweo5ITSp1Z{Y^U`l5G zJPbe!@fJJzBwDqfUfPd54{Y|Oa1q+QSgD@d#28K<%3YzAG7JPM9O#rW)>EXl;V3=dXSu}HrfDwlYlQsg2#$d!c zfp@CC;KYx@fHtPGl|?cMqw^}p{xKj82tYO-uaMNoz{eS{6K^;P{GmH_P9vXQ1ba!i zIf56?IGu#Bf3SqDG@J`Efql2$J81U%NCf>YUG21MX;O5(Xy(VJ79&0ZrXG|7_W%%B z63}Md0308CrbN(!DeLekK@!6XjtddyKmxIBfw$QN^bycK1D0SVfY&nw4eX^bd{!zz zpVSaQ>$HH<$h#$IgA|HQo~>is5wKevv9Q_v9wUCkQ@RY+8lg&sLHx*Z?(FKehh8FW zR|=v7h9Vm=K0NPZAF9~`NsK z7T88QwI`u30g~;xD4^(2yqAeZyUAka27Bl&My8qLNrF%uMl>eT2H+os^T=m6GlP)G zjBNSLORzCPPvLvhQEYla?jr+`I0B5J6B8sal{MJm=2MKEXC4djY2%;{%O6VwL3)l|044^4)ITcCM(X}9+ZeNs zVy7v+%GyjxhcCF6Tgx0;<{>*dWN_L&fQfAjXJGZ3-Zf zf){&8D3O5^TR_vVau}Du>8V$8W{cSLQTZYXKcGp1o=s?#KgTvawqr80dtP&__o< zHVo1jv#4XynZ2t+tbU2FEMtxEHt-g5@~bvcjqJB`7!O0TY)eckPKo;GXsn%=4O zalcd2&zgh%&f!2~MX%BxJjVe+SK80@N6mJv)6+DAWL;0lq-*$t>)l)NjI8&Wkd-W;=#7dYO%3~Ci&{Op5A0J`>>ztGYe6U|P zqC@5i{#O|q^aGYdL(&;^dV{4X&zk*uNmqK!KFs4ZdYuChhbypyPCtYR!3!ZK^3p9F zj>8gC~<8c za<%Z;0e`N|Q*IR~P=}{xcZ_jz*U+tOUU|uie62LpV~%|y$q_!M7&$eTagAJdC3TN6 zr=iaYUOw(!b%b}ydy0F?&RNP@Q6HP@1lDs_EEz+8dS#9sF(jqjQ+$RPJ%&v?*xxdC zb=2OkvkpYY$=7D40PtsVNV?8r~`75$8W~YY25w0TeAXTo{kk#hj95bQ%0Y-~Mlv|S_Z3=#~DzRYC}>3r-vhNjGV%Ewtj z4eB3Ygri<6nawqkP-H*BJnbPlH8wKI9eFsA-(myjTw|wGqty%SA%Es2k!ff$)9Oc@ znqfWTkQuKb!vy!#nX+41=qW3S%m~f7S(|`9F^hYd%T5jh!qldmEn`M-h@2!c$b%jv z(oh=ffg(mxmb}bj8uHH>#v%PJ)}dC65n{90$b(HdH^Pq{yVx2M1-GCT>r$p&9_d9s&J`=2 zjT(tx+Jx4i^x_HHht{JHBV!xJbAT1hbw-564QpNNZ)@GlY?4{J7(+I;*X^ezS*sY8 zo{=gt@g=skl8A*VJ*~?qk?6@+adM%KSsu^=XC_}Qb`)bhlUKa*LwL|PHp6@~7{MQEkzphHBJ6m2KlSz>Af)52vI&?g2>Vz-SB z@uXn4W9)4)Lr^@#`UpFCmuX0RAtF#?(k}L2l93!=^|GK1@lP;(2mL}ZXY*ZY8!|IK zHu=HEQa;OLlMzEmmPcy(#A;6Ih%L0U^`!$1S^J8;J*xmEW+q6#Abzp3cR+zXJfoD= zXSHwJB)5$p+jU4kVLNTsq`buYf0=#aL(xopWxL7D zB65zqC^9U@vhsPTIU4T)>JIUd(PHD+dbVQhMq5OeW*I#}L_RjOrH+xhXu~c?#-vgo zHyEitO#0t3$LoVuB}vxu91aZd2H+;G6{atGsJxHoajyoZC{ji+7dew z2|Sy6Cd#efq{bJu4ndVT#5j;xaBwG9AY$3-f4Sa_MBya85ASWKdzSVkf`Xh8&shnx zZcpYcB5>d4u8(UO@lqq0$x}nw?zT?}>>Ad)^PM*REl(7PbNTGcss+#2oXMV!kT)^^ zXnA6@+FMI8`|O#)W|_nmafo^Dh~JH$e(9UHAsj8EJ3QBGQC51(=ZB`qSpn_GFG|C(kH|&Gc@xjLggi?EG1E_|7Mxm>~xtF2_>(*u2`DOA%xMi`oxu14`UD8kIPZx4xp%)nmJgYG-i2mboD`r1tYET-G%Qsc-C= zQ=WvaV!lKpW7|fE^b$mAv5rKFW8zlMCbp8V(z2emXUzM?*OZmfWa(LJ7wcBlWJdA4 zvF-#&yJg4u^v2M9ceN8gt?QQZp9PpIw!6dl)UT| z#Lj}xkl78|+Dk6HCkEuZY(@gT%}f+D{31^&D2ugm#wj0#o6oL!`Vw7?KfxAyWK+GA z=P>`9=U&oZ5FNyBdCugwu0CJ<+$)P}>Frmah_Ig1l2RY}%#vOpch)G;G3#>A$Am=C zV0o5ltIG2E)a0KVMCeY6}Ut>D$gdk?exhVc-)c*oI0e0H%;zHuaFN=0e; zjI<3JJ@felR4Dp03VqnG4*5w*MyNNVhw)uaEyyvhp*FOt zT`M+}=M?nc$MB}C5PHsv7S!vRu~}wyu`?xPoRFh^29o)hJSnr4hcU}ovYC)sg;_>P z$cet@9XULKml#PM*pzcN3x$VBqanRSq3FeZMf=)pvFq%BA?On2IowiF5J zWwFNPbj#3#SUmwXB4+~aq=T%Zg0hb}gSH;fTfUKw&iy6@zoqAIQ}FXP=;VJRr1%_t z)9*3h?}_*~MSOjb{sqx@`IkQC{wkEgUpV21_xjBnd4Kb7=}NVA&HgzOW;Xoe*8k`K zXg&OU^C$R)iZuq=QdeQYt*!SCR)0^3qrdg~UG@5#TdzO3^7@1A*Y98bi+8p@ef!rY;7y?XW8k6&%S`i)<{ r|5^FJ-@o?i^Ur_%^(UYG`14P`a{c;`-f@2UNBo01>s4ObzkK^2Af+PB literal 0 HcmV?d00001 diff --git a/test/api/fonts/MathTestFontNone.otf b/test/api/fonts/MathTestFontNone.otf new file mode 100644 index 0000000000000000000000000000000000000000..52984eecc86b079a036841bfdce1b038eaf3ce0e GIT binary patch literal 14284 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 Date: Mon, 26 Sep 2016 10:45:58 +0100 Subject: [PATCH 0044/1326] [MATH] Fixups for previous commit --- src/hb-ot-layout-math-table.hh | 8 ++++---- src/hb-ot-layout.cc | 29 +++++++++++++++++++---------- src/hb-ot-layout.h | 2 ++ test/api/Makefile.am | 6 ++---- test/api/test-ot-layout-math.c | 16 +++++++++------- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index f4ecf3f0e..7b3c0c7d2 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -38,18 +38,18 @@ namespace OT { struct MATH { - static const hb_tag_t tableTag = HB_OT_TAG_MATH; + static const hb_tag_t tableTag = HB_OT_TAG_MATH; inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1)); + likely (version.major == 1)); } protected: - FixedVersion<>version; /* Version of the MATH table - initially set to 0x00010000u */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ public: DEFINE_SIZE_STATIC (4); }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 24d290c5c..e6316e192 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -61,7 +61,7 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); - // The MATH table is rarer so we only try and load it in _get_math + /* The MATH table is rarely used, so only try and load it in _get_math. */ layout->math_blob = NULL; layout->math = NULL; @@ -182,8 +182,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); - - if (layout->math_blob) hb_blob_destroy (layout->math_blob); + hb_blob_destroy (layout->math_blob); free (layout); } @@ -213,13 +212,22 @@ _get_math (hb_face_t *face) hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - // If the MATH table is not loaded yet, do it now. - if (!layout->math_blob) { - layout->math_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); - layout->math = OT::Sanitizer::lock_instance (layout->math_blob); +retry: + const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); + + if (unlikely (!math)) + { + hb_blob_t *blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); + math = OT::Sanitizer::lock_instance (blob); + if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) + { + hb_blob_destroy (blob); + goto retry; + } + layout->math_blob = blob; } - return *layout->math; + return *math; } @@ -1213,8 +1221,9 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, apply_string (c, lookup, accel); } + /* - * OT::MATH + * MATH */ /** @@ -1228,7 +1237,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * * Return value: #TRUE if face has a MATH table and #FALSE otherwise * - * Since: ???? + * Since: 1.4 **/ hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face) diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 7cbd794ce..e78679051 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -304,6 +304,8 @@ hb_ot_layout_get_size_params (hb_face_t *face, HB_EXTERN hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face); + + HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/test/api/Makefile.am b/test/api/Makefile.am index dae8700c3..322cd7d2a 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -52,10 +52,8 @@ if HAVE_FREETYPE TEST_PROGS += \ test-ot-layout-math \ $(NULL) -test_ot_layout_math_LDADD = $(LDADD) -test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) -test_ot_layout_math_CPPFLAGS += $(FREETYPE_CFLAGS) -test_ot_layout_math_LDADD += $(FREETYPE_LIBS) +test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS) +test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) endif # HAVE_FREETYPE endif # HAVE_OT diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index cf7d76c16..3e8fec6e0 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -37,16 +37,16 @@ static FT_Face ft_face; static hb_font_t *hb_font; static hb_face_t *hb_face; -static void -initFreeType() +static inline void +initFreeType (void) { FT_Error ft_error; if ((ft_error = FT_Init_FreeType (&ft_library))) abort(); } -static void -cleanupFreeType() +static inline void +cleanupFreeType (void) { FT_Done_FreeType (ft_library); } @@ -57,15 +57,17 @@ openFont(const char* fontFile) FT_Error ft_error; if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face))) abort(); - unsigned int fontSize = 1000; + +#define fontSize 1000 + if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); hb_face = hb_ft_face_create_cached(ft_face); } -static void -closeFont() +static inline void +closeFont (void) { hb_font_destroy (hb_font); FT_Done_Face (ft_face); From 319ff59161e6b027391f8b9fdce0db6dd44cc20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:06:41 +0200 Subject: [PATCH 0045/1326] MATH Table: Add API to access math contants. --- src/Makefile.sources | 1 + src/hb-ot-layout-math-table.hh | 146 +++++++++++++++++++++++++++- src/hb-ot-layout.cc | 25 +++++ src/hb-ot-layout.h | 5 + src/hb-ot-math.h | 100 +++++++++++++++++++ test/api/fonts/MathTestFontFull.otf | Bin 0 -> 25412 bytes test/api/test-ot-layout-math.c | 72 ++++++++++++++ 7 files changed, 345 insertions(+), 4 deletions(-) create mode 100644 src/hb-ot-math.h create mode 100644 test/api/fonts/MathTestFontFull.otf diff --git a/src/Makefile.sources b/src/Makefile.sources index cd30b12f0..5c695c5c2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -112,6 +112,7 @@ HB_OT_headers = \ hb-ot.h \ hb-ot-font.h \ hb-ot-layout.h \ + hb-ot-math.h \ hb-ot-shape.h \ hb-ot-tag.h \ $(NULL) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7b3c0c7d2..02a1d45d0 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -29,9 +29,139 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-common-private.hh" +#include "hb-ot-math.h" namespace OT { + +struct MathValueRecord +{ + inline hb_position_t get_value (hb_font_t *font, bool horizontal, + const void *base) const + { + return horizontal ? + font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) : + font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); + } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); + } + +protected: + SHORT value; /* The X or Y value in design units */ + OffsetTo deviceTable; /* Offset to the device table - from the + beginning of parent table. May be NULL. + Suggested format for device table is 1. */ + +public: + DEFINE_SIZE_STATIC (2 * 2); +}; + +struct MathConstants +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = + HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - + HB_OT_MATH_CONSTANT_MATH_LEADING + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && sanitize_math_value_records(c)); + } + + inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const + { + switch (constant) { + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: + case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: + return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); + + case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: + case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: + case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this); + + case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: + case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: + case HB_OT_MATH_CONSTANT_MATH_LEADING: + case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: + case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: + case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: + case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this); + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + + case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: + return radicalDegreeBottomRaisePercent; + } + } + +protected: + SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1]; + USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1]; + MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1]; + SHORT radicalDegreeBottomRaisePercent; + +public: + DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) + + 4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) + + 2); +}; + /* * MATH -- The MATH Table */ @@ -44,14 +174,22 @@ struct MATH { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1)); + likely (version.major == 1) && + mathConstants.sanitize (c, this)); + } + + inline bool has_math_constants (void) const { return mathConstants != 0; } + inline const MathConstants &get_math_constants (void) const { + return this+mathConstants; } protected: - FixedVersion<>version; /* Version of the MATH table - * initially set to 0x00010000u */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo mathConstants; /* MathConstants table */ + public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_STATIC (6); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index e6316e192..2ae138876 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1244,3 +1244,28 @@ hb_ot_layout_has_math_data (hb_face_t *face) { return &_get_math (face) != &OT::Null(OT::MATH); } + +/** + * hb_ot_layout_get_math_constant: + * + * @font: #hb_font_t from which to retrieve the value + * @constant: #hb_ot_math_constant_t the constant to retrieve + * + * This function returns the requested math constants as a #hb_position_t. + * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, + * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or + * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is + * actually an integer between 0 and 100 representing that percentage. + * + * Return value: the requested constant or 0 + * + * Since: ???? + **/ +hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant) +{ + const OT::MATH &math = _get_math (font->face); + return math.has_math_constants() ? + math.get_math_constants().get_value(font, constant) : 0; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index e78679051..501082e28 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -33,6 +33,7 @@ #include "hb.h" +#include "hb-ot-math.h" #include "hb-ot-tag.h" HB_BEGIN_DECLS @@ -305,6 +306,10 @@ hb_ot_layout_get_size_params (hb_face_t *face, HB_EXTERN hb_bool_t hb_ot_layout_has_math_data (hb_face_t *face); +HB_EXTERN hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant); + HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h new file mode 100644 index 000000000..7f0ec2713 --- /dev/null +++ b/src/hb-ot-math.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_MATH_H +#define HB_OT_MATH_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +typedef enum { + HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, + HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, + HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2, + HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3, + HB_OT_MATH_CONSTANT_MATH_LEADING = 4, + HB_OT_MATH_CONSTANT_AXIS_HEIGHT = 5, + HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT = 6, + HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT = 7, + HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN = 8, + HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX = 9, + HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN = 10, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP = 11, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED = 12, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN = 13, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX = 14, + HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN = 15, + HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT = 16, + HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT = 17, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN = 18, + HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN = 19, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN = 20, + HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN = 21, + HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP = 22, + HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP = 23, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN = 24, + HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN = 25, + HB_OT_MATH_CONSTANT_STACK_GAP_MIN = 26, + HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN = 27, + HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP = 28, + HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN = 29, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN = 30, + HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN = 31, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP = 32, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP = 33, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN = 34, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN = 35, + HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN = 36, + HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN = 37, + HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS = 38, + HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN = 39, + HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN = 40, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP = 41, + HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP = 42, + HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP = 43, + HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS = 44, + HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER = 45, + HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP = 46, + HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS = 47, + HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER = 48, + HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP = 49, + HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP = 50, + HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS = 51, + HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER = 52, + HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53, + HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54, + HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 +} hb_ot_math_constant_t; + +HB_END_DECLS + +#endif /* HB_OT_MATH_H */ diff --git a/test/api/fonts/MathTestFontFull.otf b/test/api/fonts/MathTestFontFull.otf new file mode 100644 index 0000000000000000000000000000000000000000..6c7c9a9511ce10cad109816e6683bcdc4d5adaa4 GIT binary patch literal 25412 zcmeHvdwf*oo%i$1Et8WFAOf{EwFjgMHiWAnQIsK>KqNPlphEF7NhZnYWG2o`2*I>v zTVJK3h*n)|TT892t*c#^($-#Zt?Q*PYrDSQdRdn(t!u4qy%!Lv?DzXT=b1S(nSizX z*}i`?@S8c$?RUSOGn2G-cD9N#u~~Sn=6w+};;9ASJH!1xW!KbEjDy0% zS^VIP+8O8TD~qP=Qke9be#K7ku?+*C_eHr~_;I4#y9(p4>37d^afVzhfYM*8kKmR3 z*x3;;HVgZtyEQFmo_p|vIUD~tnj{`o@3@@on_)TEQcPMn-?{dPl7;QgwO3RxH2nI+ zq(xq5-jD0W&UFCSG3UBMoUrIVSXcVM=Zqjpt7|Fjg%h1?kEmF-U|BM>&D!ahk-Jjr%tCaPwF;g zt5M+QET697hH?zzoaUqp?{UlwE6qd{UuGv|Ph-u7JR1Npj3c58ujF?aWAe^b@){E7 zs_P82XBB8N4f$!6L7Yf~Q}P|hdlIvK&}l2qHz~bZV$NUXpXJhjn+S^*B~vTjJ8{(n z+tjJq4!n-1eH)z9(-y0jsn-pTFAicq zBY^R%d7;n76^1Tcr9gvNx!(q_CjJJok`$L>wj1kd<68E}WzvYFg9)Gaxk+QJj%S+R=

    WsnN!JE?xZBf> zrL||%4{2|$9ZE$XVQ$tsib5w`>%l)WcXVxNFPICdSeJ6rxih`yk8Amr&UlUXU+RR~ zAoto5)DN{s8>WDy95O z>(+3hHB9cQU3!W39(NTd70Q^418QJI#jD93`M#dxS6k(BSTLq^l*@kf7}_G|ImF6} zOl}y_IzHW;Q18Y14jX=u#3}09NEQKqgOF+jTF`in9NgOtj&i)@GNh57Rb2b6_WXQ4 zHRpPTa*;l5pYPQsThyZ(HK5A206GDzydB_b#!>pK8IB%$6<(cHs2jr#?Ubt_%nY<2 z_l>osJA&;ZounmJK_iTI$}kI9SnJ-M-i-$`+UY;6ee@ODFC{L+9OFf2pEPhXcN_1} zmejf1Qu;PILuc_M_NQ=yqnw1yFU$y(n7H%%FCCGbFSN4GHq3uIhtEL2kRP+|uCxU_ z(?7+jCUw&`TDnO1I3A$g!7iD7 zGWXlCDPurKDebLi*~2i}NL}wXyyo|&#Wn5TV-G>pQmlX9p+ZI+^d`E-*OQi>cVX?gQ)xsU;Jq;`f-O!4)T!(Gf=bb*cwtwbR(jAp>HJB{Fz0K_ zY1zr4>5Fomw)P$E3A{IrDla#7(=|R{>Ljo-577^_FIX69Eihx5>VIsx>4}<>?tM5m zo$iR!m*_0W6>T}gVXoWLYbGP`-1uD|_tN8ajbJ3l6=rkVJS8xDSntMm+O)TRqQE@o zj=o&A;QcjMa!*G{n>oKLd&g#^H=1JfnR^BkW!krxhnP=j1grk_h_ zpEbC~_cq-PG56%>7-FG3q)dAH-i-J2)KRg_Lrrrx?|BMyj*gvUWoq5o>uPU0`&=Kc zy;t)^TlG3sdV!Msz0(}eW_%`z@j-QiG^@8$l2zH+oX40ctF*<94= zj)5_*Ba@aizQAW#N!9J=_G^3TXNI~vW)@`qF}}~!I-88w$FtugMxM|bD(u*(g?#@s zT_5?RcIMz+-+>YrGt@@B7WQ`ih#PuI0{fZQSetWC=9umDGYaNrS~r#T%$yF``LpWq zl}|!ROWT*4q#s9%VrSkVx1`8-%^Ur(M^Q6(i#if=5@;^E6lT_ZdQq-p)%_8lqA;fO z@4l13OWt(HXy~~0Os!Ir?01QmvC8_YJL~-3O6S&;6FUo?tiif zrqi>E+zaLRqBWr0nT-vNL)U&jh0Ar#3CA|(o>M;wE6n-Y8|mA|Lv$~}EUmSpJ;hRf ztM5%rB`?HfEN$*F7b#nlS9+7dXSAJPx9U`68t793k0sWIAwv6H*I)s`sMIdQ+vlE=CWVrRi;$m|A9?IjhCnFHKi zHa&sXW+dut_->w3kQbxl93{6Gj(_j!#;?7L{-<*bEizuc)X!o5oabJ;zhHLIdUI1I zy<+wG=+C`!Uafok!Y3lE=hURGk9=lHE08*Cl$J5q<&O0U?LnQ{dzlsy%0AyZ+Gll) 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 saECM>-&HwHt(}POYX Date: Mon, 26 Sep 2016 11:15:59 +0100 Subject: [PATCH 0046/1326] [MATH] Fixups for math constants commit --- src/hb-ot-layout-math-table.hh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 02a1d45d0..c215d3221 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -36,13 +36,10 @@ namespace OT { struct MathValueRecord { - inline hb_position_t get_value (hb_font_t *font, bool horizontal, - const void *base) const - { - return horizontal ? - font->em_scale_x (value) + (base+deviceTable).get_x_delta (font) : - font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); - } + inline hb_position_t get_x_value (hb_font_t *font, const void *base) const + { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } + inline hb_position_t get_y_value (hb_font_t *font, const void *base) const + { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -57,7 +54,7 @@ protected: Suggested format for device table is 1. */ public: - DEFINE_SIZE_STATIC (2 * 2); + DEFINE_SIZE_STATIC (4); }; struct MathConstants @@ -90,7 +87,7 @@ struct MathConstants case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: - return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, true, this); + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this); case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: @@ -139,7 +136,7 @@ struct MathConstants case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: - return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_value(font, false, this); + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: @@ -147,6 +144,8 @@ struct MathConstants case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: return radicalDegreeBottomRaisePercent; + default: + return 0; } } From 6fd2fe418dc838743f0d4a8a2222cdcaf587500c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:24:39 +0100 Subject: [PATCH 0047/1326] [MATH] Fixup math constants commit a bit more --- src/hb-ot-layout-math-table.hh | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index c215d3221..e65680b5a 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -62,9 +62,7 @@ struct MathConstants inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - unsigned int count = - HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - - HB_OT_MATH_CONSTANT_MATH_LEADING + 1; + unsigned int count = ARRAY_LENGTH (mathValueRecords); for (unsigned int i = 0; i < count; i++) if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); return_trace (true); @@ -79,6 +77,11 @@ struct MathConstants inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const { switch (constant) { + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); @@ -138,27 +141,22 @@ struct MathConstants case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); - case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: - case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: - return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; - case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: return radicalDegreeBottomRaisePercent; + default: return 0; } } protected: - SHORT percentScaleDown[HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1]; - USHORT minHeight[HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT + 1]; - MathValueRecord mathValueRecords[HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1]; + SHORT percentScaleDown[2]; + USHORT minHeight[2]; + MathValueRecord mathValueRecords[51]; SHORT radicalDegreeBottomRaisePercent; public: - DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN + 1) + - 4 * (HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE - HB_OT_MATH_CONSTANT_MATH_LEADING + 1) + - 2); + DEFINE_SIZE_STATIC (214); }; /* From d7182d129612c619b9026ee9b15f2dcfada132db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:15:31 +0200 Subject: [PATCH 0048/1326] MATH Table: Add API to access glyph info. --- src/hb-ot-layout-math-table.hh | 271 +++++++++++++++++++++++- src/hb-ot-layout.cc | 114 ++++++++++ src/hb-ot-layout.h | 18 ++ src/hb-ot-math.h | 7 + test/api/fonts/MathTestFontPartial1.otf | Bin 0 -> 14348 bytes test/api/fonts/MathTestFontPartial2.otf | Bin 0 -> 14356 bytes test/api/fonts/MathTestFontPartial3.otf | Bin 0 -> 14380 bytes test/api/test-ot-layout-math.c | 155 ++++++++++++++ 8 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 test/api/fonts/MathTestFontPartial1.otf create mode 100644 test/api/fonts/MathTestFontPartial2.otf create mode 100644 test/api/fonts/MathTestFontPartial3.otf diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index e65680b5a..2eb0d9228 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -159,6 +159,267 @@ public: DEFINE_SIZE_STATIC (214); }; +struct MathItalicsCorrectionInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+coverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= italicsCorrection.len)) return false; + value = italicsCorrection[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo coverage; /* Offset to Coverage table - + from the beginning of + MathItalicsCorrectionInfo + table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + defining italics correction + values for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection); +}; + +struct MathTopAccentAttachment +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); + } + + inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, + hb_position_t &value) const + { + unsigned int index = (this+topAccentCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= topAccentAttachment.len)) return false; + value = topAccentAttachment[index].get_x_value(font, this); + return true; + } + +protected: + OffsetTo topAccentCoverage; /* Offset to Coverage table - + from the beginning of + MathTopAccentAttachment + table. */ + ArrayOf topAccentAttachment; /* Array of MathValueRecords + defining top accent + attachment points for each + covered glyph. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); +}; + +struct MathKern +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = 2 * heightCount + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); + } + + inline hb_position_t get_value (hb_font_t *font, + hb_position_t &correction_height) const + { + const MathValueRecord* correctionHeight = mathValueRecords; + const MathValueRecord* kernValue = mathValueRecords + heightCount; + // The description of the MathKern table is a ambiguous, but interpreting + // "between the two heights found at those indexes" for 0 < i < len as + // + // correctionHeight[i-1] < correction_height <= correctionHeight[i] + // + // makes the result consistent with the limit cases and we can just use the + // binary search algorithm of std::upper_bound: + unsigned int count = heightCount; + unsigned int i = 0; + while (count > 0) { + unsigned int half = count / 2; + hb_position_t height = + correctionHeight[i + half].get_y_value(font, this); + if (height < correction_height) { + i += half + 1; + count -= half + 1; + } else + count = half; + } + return kernValue[i].get_x_value(font, this); + } + +protected: + USHORT heightCount; + MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at + which the kern value changes. + Sorted by the height value in + design units. */ + /* Array of kern values corresponding + to heights. */ + +public: + DEFINE_SIZE_ARRAY (2, mathValueRecords); +}; + +struct MathKernInfoRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) && + mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base)); + } + + inline bool has_math_kern (hb_ot_math_kern_t kern) const { + return mathKern[kern] != 0; + } + inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, + const void *base) const { + return base+mathKern[kern]; + } + +protected: + /* Offset to MathKern table for each corner - + from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1]; + +public: + DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT - + HB_OT_MATH_KERN_TOP_RIGHT + 1)); +}; + +struct MathKernInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); + } + + inline bool + get_math_kern_info_record (hb_codepoint_t glyph, + const MathKernInfoRecord *&record) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + if (unlikely (index >= mathKernInfoRecords.len)) return false; + record = &mathKernInfoRecords[index]; + return true; + } + +protected: + OffsetTo mathKernCoverage; /* Offset to Coverage table - + from the beginning of the + MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + MathKernInfoRecords, + per-glyph information for + mathematical positioning + of subscripts and + superscripts. */ + +public: + DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords); +}; + +struct MathGlyphInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); + } + + inline bool has_math_italics_correction_info (void) const { + return mathItalicsCorrectionInfo != 0; + } + inline const MathItalicsCorrectionInfo& + get_math_italics_correction_info (void) const { + return this+mathItalicsCorrectionInfo; + } + + inline bool has_math_top_accent_attachment (void) const { + return mathTopAccentAttachment != 0; + } + inline const MathTopAccentAttachment& + get_math_top_accent_attachment (void) const { + return this+mathTopAccentAttachment; + } + + inline bool is_extended_shape (hb_codepoint_t glyph) const + { + if (likely (extendedShapeCoverage == 0)) return false; + unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + return true; + } + + inline bool has_math_kern_info (void) const { return mathKernInfo != 0; } + inline const MathKernInfo &get_math_kern_info (void) const { + return this+mathKernInfo; + } + +protected: + /* Offset to MathItalicsCorrectionInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathItalicsCorrectionInfo; + + /* Offset to MathTopAccentAttachment table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathTopAccentAttachment; + + /* Offset to coverage table for Extended Shape glyphs - + from the beginning of MathGlyphInfo table. When the left or right glyph of + a box is an extended shape variant, the (ink) box (and not the default + position defined by values in MathConstants table) should be used for + vertical positioning purposes. May be NULL.. */ + OffsetTo extendedShapeCoverage; + + /* Offset to MathKernInfo table - + from the beginning of MathGlyphInfo table. */ + OffsetTo mathKernInfo; + +public: + DEFINE_SIZE_STATIC (4 * 2); +}; + /* * MATH -- The MATH Table */ @@ -172,7 +433,8 @@ struct MATH TRACE_SANITIZE (this); return_trace (version.sanitize (c) && likely (version.major == 1) && - mathConstants.sanitize (c, this)); + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this)); } inline bool has_math_constants (void) const { return mathConstants != 0; } @@ -180,13 +442,18 @@ struct MATH return this+mathConstants; } + inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } + inline const MathGlyphInfo &get_math_glyph_info (void) const { + return this+mathGlyphInfo; + } protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants; /* MathConstants table */ + OffsetTo mathGlyphInfo; /* MathGlyphInfo table */ public: - DEFINE_SIZE_STATIC (6); + DEFINE_SIZE_STATIC (8); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 2ae138876..f14611b47 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1269,3 +1269,117 @@ hb_ot_layout_get_math_constant (hb_font_t *font, return math.has_math_constants() ? math.get_math_constants().get_value(font, constant) : 0; } + +/** + * hb_ot_layout_get_math_italic_correction: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the italic correction of the glyph or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_italics_correction_info()) { + hb_position_t value; + if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_get_math_top_accent_attachment: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the top accent attachment of the glyph or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_top_accent_attachment()) { + hb_position_t value; + if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, + value)) + return value; + } + } + return 0; +} + +/** + * hb_ot_layout_is_math_extended_shape: + * + * @font: a #hb_font_t to test + * @glyph: a glyph index to test + * + * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise + * + * Since: ???? + **/ +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (face); + return math.has_math_glyph_info() && + math.get_math_glyph_info().is_extended_shape(glyph); +} + +/** + * hb_ot_layout_get_math_kerning: + * + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * @kern: the #hb_ot_math_kern_t from which to retrieve the value + * @correction_height: the correction height to use to determine the kerning. + * + * This function tries to retrieve the MathKern table for the specified font, + * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the + * MathKern table to find one value that is greater or equal to specified + * correction_height. If one is found the corresponding value from the list of + * kerns is returned and otherwise the last kern value is returned. + * + * Return value: requested kerning or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) +{ + const OT::MATH &math = _get_math (font->face); + if (math.has_math_glyph_info()) { + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + if (glyphInfo.has_math_kern_info()) { + const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); + const OT::MathKernInfoRecord *kernInfoRecord; + if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) && + kernInfoRecord->has_math_kern(kern)) { + return kernInfoRecord-> + get_math_kern(kern, &kernInfo).get_value(font, correction_height); + } + } + } + + return 0; +} diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 501082e28..ffb6321c7 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -310,6 +310,24 @@ HB_EXTERN hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant); +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 7f0ec2713..a62b4b612 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -95,6 +95,13 @@ typedef enum { HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 } hb_ot_math_constant_t; +typedef enum { + HB_OT_MATH_KERN_TOP_RIGHT = 0, + HB_OT_MATH_KERN_TOP_LEFT = 1, + HB_OT_MATH_KERN_BOTTOM_RIGHT = 2, + HB_OT_MATH_KERN_BOTTOM_LEFT = 3 +} hb_ot_math_kern_t; + HB_END_DECLS #endif /* HB_OT_MATH_H */ diff --git a/test/api/fonts/MathTestFontPartial1.otf b/test/api/fonts/MathTestFontPartial1.otf new file mode 100644 index 0000000000000000000000000000000000000000..b3bf36e33efb8a5b0f4f33f74f952fb26f34c42c GIT binary patch literal 14348 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 P{^9TW@B^CmujBp)n>Hxn literal 0 HcmV?d00001 diff --git a/test/api/fonts/MathTestFontPartial3.otf b/test/api/fonts/MathTestFontPartial3.otf new file mode 100644 index 0000000000000000000000000000000000000000..ca18a9a228facf9472f09122d6646eeeb3a0ff86 GIT binary patch literal 14380 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 a{<`%z^t-37;b#LsZ{UZYnTzdT&HWOy+$iAy literal 0 HcmV?d00001 diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index 219959b65..5ba583f1b 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -160,6 +160,157 @@ test_get_math_constant (void) cleanupFreeType(); } +static void +test_get_math_italic_correction (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197); + g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150); + g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452); + closeFont(); + + cleanupFreeType(); + +} + +static void +test_get_math_top_accent_attachment (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment. + g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318); + closeFont(); + + cleanupFreeType(); +} + +static void +test_is_math_extended_shape (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); + g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); + g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph)); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_math_kerning (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right + g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + + closeFont(); + + cleanupFreeType(); +} + + int main (int argc, char **argv) { @@ -167,6 +318,10 @@ main (int argc, char **argv) hb_test_add (test_has_math_data); hb_test_add (test_get_math_constant); + hb_test_add (test_get_math_italic_correction); + hb_test_add (test_get_math_top_accent_attachment); + hb_test_add (test_is_math_extended_shape); + hb_test_add (test_get_math_kerning); return hb_test_run(); } From 8a8cfad9a0834fe278a747c1d755144bd78f564b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:47:05 +0100 Subject: [PATCH 0049/1326] [MATH] Cleanup previous commit a bit --- src/hb-ot-layout-math-table.hh | 186 ++++++++++++++++----------------- src/hb-ot-layout.cc | 30 +++--- src/hb-ot-layout.h | 14 +-- 3 files changed, 113 insertions(+), 117 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 2eb0d9228..7f6c6b09c 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -48,10 +48,10 @@ struct MathValueRecord } protected: - SHORT value; /* The X or Y value in design units */ - OffsetTo deviceTable; /* Offset to the device table - from the - beginning of parent table. May be NULL. - Suggested format for device table is 1. */ + SHORT value; /* The X or Y value in design units */ + OffsetTo deviceTable; /* Offset to the device table - from the + * beginning of parent table. May be NULL. + * Suggested format for device table is 1. */ public: DEFINE_SIZE_STATIC (4); @@ -62,9 +62,12 @@ struct MathConstants inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); + unsigned int count = ARRAY_LENGTH (mathValueRecords); for (unsigned int i = 0; i < count; i++) - if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + if (!mathValueRecords[i].sanitize (c, this)) + return_trace (false); + return_trace (true); } @@ -165,12 +168,12 @@ struct MathItalicsCorrectionInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - coverage.sanitize (c, this) && - italicsCorrection.sanitize (c, this)); + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); } inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + hb_position_t &value) const { unsigned int index = (this+coverage).get_coverage (glyph); if (likely (index == NOT_COVERED)) return false; @@ -180,17 +183,17 @@ struct MathItalicsCorrectionInfo } protected: - OffsetTo coverage; /* Offset to Coverage table - - from the beginning of - MathItalicsCorrectionInfo - table. */ - ArrayOf italicsCorrection; /* Array of MathValueRecords - defining italics correction - values for each - covered glyph. */ + OffsetTo coverage; /* Offset to Coverage table - + * from the beginning of + * MathItalicsCorrectionInfo + * table. */ + ArrayOf italicsCorrection; /* Array of MathValueRecords + * defining italics correction + * values for each + * covered glyph. */ public: - DEFINE_SIZE_ARRAY (2 + 2, italicsCorrection); + DEFINE_SIZE_ARRAY (4, italicsCorrection); }; struct MathTopAccentAttachment @@ -199,12 +202,12 @@ struct MathTopAccentAttachment { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - topAccentCoverage.sanitize (c, this) && - topAccentAttachment.sanitize (c, this)); + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); } inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + hb_position_t &value) const { unsigned int index = (this+topAccentCoverage).get_coverage (glyph); if (likely (index == NOT_COVERED)) return false; @@ -215,13 +218,13 @@ struct MathTopAccentAttachment protected: OffsetTo topAccentCoverage; /* Offset to Coverage table - - from the beginning of - MathTopAccentAttachment - table. */ + * from the beginning of + * MathTopAccentAttachment + * table. */ ArrayOf topAccentAttachment; /* Array of MathValueRecords - defining top accent - attachment points for each - covered glyph. */ + * defining top accent + * attachment points for each + * covered glyph. */ public: DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); @@ -242,14 +245,14 @@ struct MathKern { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (mathValueRecords, - mathValueRecords[0].static_size, - 2 * heightCount + 1) && - sanitize_math_value_records (c)); + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); } inline hb_position_t get_value (hb_font_t *font, - hb_position_t &correction_height) const + hb_position_t &correction_height) const { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; @@ -265,12 +268,12 @@ struct MathKern while (count > 0) { unsigned int half = count / 2; hb_position_t height = - correctionHeight[i + half].get_y_value(font, this); + correctionHeight[i + half].get_y_value(font, this); if (height < correction_height) { - i += half + 1; - count -= half + 1; + i += half + 1; + count -= half + 1; } else - count = half; + count = half; } return kernValue[i].get_x_value(font, this); } @@ -278,11 +281,11 @@ struct MathKern protected: USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at - which the kern value changes. - Sorted by the height value in - design units. */ - /* Array of kern values corresponding - to heights. */ + * which the kern value changes. + * Sorted by the height value in + * design units. */ + /* Array of kern values corresponding + * to heights. */ public: DEFINE_SIZE_ARRAY (2, mathValueRecords); @@ -293,30 +296,30 @@ struct MathKernInfoRecord inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - mathKern[HB_OT_MATH_KERN_TOP_RIGHT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_TOP_LEFT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_BOTTOM_RIGHT].sanitize (c, base) && - mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT].sanitize (c, base)); + + unsigned int count = ARRAY_LENGTH (mathKern); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!mathKern[i].sanitize (c, base))) + return_trace (false); + + return_trace (true); } - inline bool has_math_kern (hb_ot_math_kern_t kern) const { - return mathKern[kern] != 0; - } inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, - const void *base) const { - return base+mathKern[kern]; + const void *base) const + { + unsigned int idx = kern; + if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern); + return base+mathKern[idx]; } protected: /* Offset to MathKern table for each corner - - from the beginning of MathKernInfo table. May be NULL. */ - OffsetTo mathKern[HB_OT_MATH_KERN_BOTTOM_LEFT - - HB_OT_MATH_KERN_TOP_RIGHT + 1]; + * from the beginning of MathKernInfo table. May be NULL. */ + OffsetTo mathKern[4]; public: - DEFINE_SIZE_STATIC (2 * (HB_OT_MATH_KERN_BOTTOM_LEFT - - HB_OT_MATH_KERN_TOP_RIGHT + 1)); + DEFINE_SIZE_STATIC (8); }; struct MathKernInfo @@ -325,34 +328,30 @@ struct MathKernInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - mathKernCoverage.sanitize (c, this) && - mathKernInfoRecords.sanitize (c, this)); + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); } - inline bool - get_math_kern_info_record (hb_codepoint_t glyph, - const MathKernInfoRecord *&record) const + inline const MathKernInfoRecord& + get_math_kern_info_record (hb_codepoint_t glyph) const { unsigned int index = (this+mathKernCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= mathKernInfoRecords.len)) return false; - record = &mathKernInfoRecords[index]; - return true; + return mathKernInfoRecords[index]; } protected: - OffsetTo mathKernCoverage; /* Offset to Coverage table - - from the beginning of the - MathKernInfo table. */ - ArrayOf mathKernInfoRecords; /* Array of - MathKernInfoRecords, - per-glyph information for - mathematical positioning - of subscripts and - superscripts. */ + OffsetTo mathKernCoverage; /* Offset to Coverage table - + * from the beginning of the + * MathKernInfo table. */ + ArrayOf mathKernInfoRecords; /* Array of + * MathKernInfoRecords, + * per-glyph information for + * mathematical positioning + * of subscripts and + * superscripts. */ public: - DEFINE_SIZE_ARRAY (2 + 2, mathKernInfoRecords); + DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); }; struct MathGlyphInfo @@ -361,10 +360,10 @@ struct MathGlyphInfo { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - mathItalicsCorrectionInfo.sanitize (c, this) && - mathTopAccentAttachment.sanitize (c, this) && - extendedShapeCoverage.sanitize (c, this) && - mathKernInfo.sanitize(c, this)); + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); } inline bool has_math_italics_correction_info (void) const { @@ -398,28 +397,29 @@ struct MathGlyphInfo protected: /* Offset to MathItalicsCorrectionInfo table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathItalicsCorrectionInfo; /* Offset to MathTopAccentAttachment table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathTopAccentAttachment; /* Offset to coverage table for Extended Shape glyphs - - from the beginning of MathGlyphInfo table. When the left or right glyph of - a box is an extended shape variant, the (ink) box (and not the default - position defined by values in MathConstants table) should be used for - vertical positioning purposes. May be NULL.. */ + * from the beginning of MathGlyphInfo table. When the left or right glyph of + * a box is an extended shape variant, the (ink) box (and not the default + * position defined by values in MathConstants table) should be used for + * vertical positioning purposes. May be NULL.. */ OffsetTo extendedShapeCoverage; /* Offset to MathKernInfo table - - from the beginning of MathGlyphInfo table. */ + * from the beginning of MathGlyphInfo table. */ OffsetTo mathKernInfo; public: - DEFINE_SIZE_STATIC (4 * 2); + DEFINE_SIZE_STATIC (8); }; + /* * MATH -- The MATH Table */ @@ -432,9 +432,9 @@ struct MATH { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1) && - mathConstants.sanitize (c, this) && - mathGlyphInfo.sanitize (c, this)); + likely (version.major == 1) && + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this)); } inline bool has_math_constants (void) const { return mathConstants != 0; } @@ -447,10 +447,10 @@ struct MATH return this+mathGlyphInfo; } protected: - FixedVersion<>version; /* Version of the MATH table - * initially set to 0x00010000u */ - OffsetTo mathConstants; /* MathConstants table */ - OffsetTo mathGlyphInfo; /* MathGlyphInfo table */ + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo mathConstants;/* MathConstants table */ + OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ public: DEFINE_SIZE_STATIC (8); diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index f14611b47..3dcdfb697 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1263,7 +1263,7 @@ hb_ot_layout_has_math_data (hb_face_t *face) **/ hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant) + hb_ot_math_constant_t constant) { const OT::MATH &math = _get_math (font->face); return math.has_math_constants() ? @@ -1282,7 +1282,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { @@ -1290,8 +1290,8 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, if (glyphInfo.has_math_italics_correction_info()) { hb_position_t value; if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, - value)) - return value; + value)) + return value; } } return 0; @@ -1309,7 +1309,7 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { @@ -1317,8 +1317,8 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, if (glyphInfo.has_math_top_accent_attachment()) { hb_position_t value; if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, - value)) - return value; + value)) + return value; } } return 0; @@ -1336,7 +1336,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, **/ HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph) + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); return math.has_math_glyph_info() && @@ -1363,21 +1363,17 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height) + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); if (math.has_math_glyph_info()) { const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); if (glyphInfo.has_math_kern_info()) { const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord *kernInfoRecord; - if (kernInfo.get_math_kern_info_record(glyph, kernInfoRecord) && - kernInfoRecord->has_math_kern(kern)) { - return kernInfoRecord-> - get_math_kern(kern, &kernInfo).get_value(font, correction_height); - } + const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); + return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); } } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index ffb6321c7..f9ed2d82d 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -308,25 +308,25 @@ hb_ot_layout_has_math_data (hb_face_t *face); HB_EXTERN hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); + hb_ot_math_constant_t constant); HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); HB_END_DECLS From 54c0cc38fba24fa4370231408ba121589b190a28 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 11:56:40 +0100 Subject: [PATCH 0050/1326] [MATH] Clean up get_math_constant implementation --- src/hb-ot-layout-math-table.hh | 10 +++++----- src/hb-ot-layout.cc | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7f6c6b09c..cbdee485f 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -77,7 +77,8 @@ struct MathConstants return_trace (c->check_struct (this) && sanitize_math_value_records(c)); } - inline hb_position_t get_value (hb_font_t *font, hb_ot_math_constant_t constant) const + inline hb_position_t get_value (hb_ot_math_constant_t constant, + hb_font_t *font) const { switch (constant) { @@ -437,10 +438,9 @@ struct MATH mathGlyphInfo.sanitize (c, this)); } - inline bool has_math_constants (void) const { return mathConstants != 0; } - inline const MathConstants &get_math_constants (void) const { - return this+mathConstants; - } + inline hb_position_t get_constant (hb_ot_math_constant_t constant, + hb_font_t *font) const + { return (this+mathConstants).get_value (constant, font); } inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } inline const MathGlyphInfo &get_math_glyph_info (void) const { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3dcdfb697..359d94185 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1259,15 +1259,14 @@ hb_ot_layout_has_math_data (hb_face_t *face) * * Return value: the requested constant or 0 * - * Since: ???? + * Since: 1.4 **/ hb_position_t hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant) { const OT::MATH &math = _get_math (font->face); - return math.has_math_constants() ? - math.get_math_constants().get_value(font, constant) : 0; + return math.get_constant(constant, font); } /** From 06003f71ba0d0327fb1a17098a9d7faa8fb336f0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:07:29 +0100 Subject: [PATCH 0051/1326] [MATH] Clean up a bit more --- src/hb-ot-layout-math-table.hh | 12 +------ src/hb-ot-layout.cc | 57 +++++++++++++--------------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index cbdee485f..53038e3ec 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -367,17 +367,11 @@ struct MathGlyphInfo mathKernInfo.sanitize(c, this)); } - inline bool has_math_italics_correction_info (void) const { - return mathItalicsCorrectionInfo != 0; - } inline const MathItalicsCorrectionInfo& get_math_italics_correction_info (void) const { return this+mathItalicsCorrectionInfo; } - inline bool has_math_top_accent_attachment (void) const { - return mathTopAccentAttachment != 0; - } inline const MathTopAccentAttachment& get_math_top_accent_attachment (void) const { return this+mathTopAccentAttachment; @@ -385,13 +379,10 @@ struct MathGlyphInfo inline bool is_extended_shape (hb_codepoint_t glyph) const { - if (likely (extendedShapeCoverage == 0)) return false; unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - return true; + return index != NOT_COVERED; } - inline bool has_math_kern_info (void) const { return mathKernInfo != 0; } inline const MathKernInfo &get_math_kern_info (void) const { return this+mathKernInfo; } @@ -442,7 +433,6 @@ struct MATH hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } - inline bool has_math_glyph_info (void) const { return mathGlyphInfo != 0; } inline const MathGlyphInfo &get_math_glyph_info (void) const { return this+mathGlyphInfo; } diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 359d94185..6fa61a44a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1277,23 +1277,19 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * * Return value: the italic correction of the glyph or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_italic_correction (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_italics_correction_info()) { - hb_position_t value; - if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, - value)) - return value; - } - } - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + hb_position_t value; + if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value)) + return value; + else + return 0; } /** @@ -1304,23 +1300,19 @@ hb_ot_layout_get_math_italic_correction (hb_font_t *font, * * Return value: the top accent attachment of the glyph or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_top_accent_attachment()) { - hb_position_t value; - if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, - value)) - return value; - } - } - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + hb_position_t value; + if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value)) + return value; + else + return 0; // XXX font->get_glyph_h_advance (glyph) / 2; } /** @@ -1331,15 +1323,14 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); - return math.has_math_glyph_info() && - math.get_math_glyph_info().is_extended_shape(glyph); + return math.get_math_glyph_info().is_extended_shape(glyph); } /** @@ -1358,7 +1349,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * * Return value: requested kerning or 0 * - * Since: ???? + * Since: 1.4 **/ HB_EXTERN hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, @@ -1367,14 +1358,8 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); - if (math.has_math_glyph_info()) { - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - if (glyphInfo.has_math_kern_info()) { - const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); - return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); - } - } - - return 0; + const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); + const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); + const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); + return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); } From 8bcf517fe59608d2247a8974445b3ff0f4b4b4ac Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:12:41 +0100 Subject: [PATCH 0052/1326] [MATH] Clean up get_italics_correction() --- src/hb-ot-layout-math-table.hh | 16 ++++++++-------- src/hb-ot-layout.cc | 17 ++++++----------- src/hb-ot-layout.h | 4 ++-- test/api/test-ot-layout-math.c | 18 +++++++++--------- 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 53038e3ec..3899b1612 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -173,13 +173,11 @@ struct MathItalicsCorrectionInfo italicsCorrection.sanitize (c, this)); } - inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const { unsigned int index = (this+coverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= italicsCorrection.len)) return false; - value = italicsCorrection[index].get_x_value(font, this); + return italicsCorrection[index].get_x_value (font, this); return true; } @@ -367,9 +365,11 @@ struct MathGlyphInfo mathKernInfo.sanitize(c, this)); } - inline const MathItalicsCorrectionInfo& - get_math_italics_correction_info (void) const { - return this+mathItalicsCorrectionInfo; + inline hb_position_t + get_italics_correction (hb_codepoint_t glyph, + hb_font_t *font) const + { + return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } inline const MathTopAccentAttachment& diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6fa61a44a..5f171ca2b 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1270,26 +1270,21 @@ hb_ot_layout_get_math_constant (hb_font_t *font, } /** - * hb_ot_layout_get_math_italic_correction: + * hb_ot_layout_get_math_italics_correction: * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value * - * Return value: the italic correction of the glyph or 0 + * Return value: the italics correction of the glyph or 0 * * Since: 1.4 **/ HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph) +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - hb_position_t value; - if (glyphInfo.get_math_italics_correction_info().get_value(font, glyph, value)) - return value; - else - return 0; + return math.get_math_glyph_info().get_italics_correction (glyph, font); } /** @@ -1330,7 +1325,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); - return math.get_math_glyph_info().is_extended_shape(glyph); + return math.get_math_glyph_info().is_extended_shape (glyph); } /** diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index f9ed2d82d..9c1c57bb4 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -311,8 +311,8 @@ hb_ot_layout_get_math_constant (hb_font_t *font, hb_ot_math_constant_t constant); HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index 5ba583f1b..a6f4453cc 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -161,35 +161,35 @@ test_get_math_constant (void) } static void -test_get_math_italic_correction (void) +test_get_math_italics_correction (void) { hb_codepoint_t glyph; initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 197); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197); g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 150); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150); g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction (hb_font, glyph), ==, 452); + g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452); closeFont(); cleanupFreeType(); @@ -318,7 +318,7 @@ main (int argc, char **argv) hb_test_add (test_has_math_data); hb_test_add (test_get_math_constant); - hb_test_add (test_get_math_italic_correction); + hb_test_add (test_get_math_italics_correction); hb_test_add (test_get_math_top_accent_attachment); hb_test_add (test_is_math_extended_shape); hb_test_add (test_get_math_kerning); From 17ff30e9afde79e41c17786223293e867b49ebba Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 12:18:32 +0100 Subject: [PATCH 0053/1326] [MATH] Clean up get_top_accent_attachment() Note, the function now returns "half of horizontal advance width" if top accent attachment for glyph is not explicitly defined. This is what the spec requires. Updated tests. --- src/hb-ot-layout-math-table.hh | 31 +++++++++++-------------------- src/hb-ot-layout.cc | 7 +------ test/api/test-ot-layout-math.c | 8 ++++---- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 3899b1612..8f7ce3db2 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -178,7 +178,6 @@ struct MathItalicsCorrectionInfo { unsigned int index = (this+coverage).get_coverage (glyph); return italicsCorrection[index].get_x_value (font, this); - return true; } protected: @@ -205,14 +204,13 @@ struct MathTopAccentAttachment topAccentAttachment.sanitize (c, this)); } - inline bool get_value (hb_font_t *font, hb_codepoint_t glyph, - hb_position_t &value) const + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const { unsigned int index = (this+topAccentCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; - if (unlikely (index >= topAccentAttachment.len)) return false; - value = topAccentAttachment[index].get_x_value(font, this); - return true; + if (index == NOT_COVERED) + return font->get_glyph_h_advance (glyph) / 2; + return topAccentAttachment[index].get_x_value(font, this); } protected: @@ -366,22 +364,15 @@ struct MathGlyphInfo } inline hb_position_t - get_italics_correction (hb_codepoint_t glyph, - hb_font_t *font) const - { - return (this+mathItalicsCorrectionInfo).get_value (glyph, font); - } + get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } - inline const MathTopAccentAttachment& - get_math_top_accent_attachment (void) const { - return this+mathTopAccentAttachment; - } + inline hb_position_t + get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathTopAccentAttachment).get_value (glyph, font); } inline bool is_extended_shape (hb_codepoint_t glyph) const - { - unsigned int index = (this+extendedShapeCoverage).get_coverage (glyph); - return index != NOT_COVERED; - } + { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } inline const MathKernInfo &get_math_kern_info (void) const { return this+mathKernInfo; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5f171ca2b..6d6cf5bc6 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1302,12 +1302,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - hb_position_t value; - if (glyphInfo.get_math_top_accent_attachment().get_value(font, glyph, value)) - return value; - else - return 0; // XXX font->get_glyph_h_advance (glyph) / 2; + return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); } /** diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index a6f4453cc..d7121a2a2 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -204,22 +204,22 @@ test_get_math_top_accent_attachment (void) openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // MathTopAccentAttachment empty + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 0); // Glyph without top accent attachment. + g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); From 94f5df5626b223ad92d0c167f560c1f2e2f19042 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 13:31:47 +0100 Subject: [PATCH 0054/1326] [MATH] Clean up get_kerning() --- src/hb-ot-layout-math-table.hh | 29 +++++++++++++++++------------ src/hb-ot-layout.cc | 5 +---- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 8f7ce3db2..4600eab32 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -248,8 +248,7 @@ struct MathKern sanitize_math_value_records (c)); } - inline hb_position_t get_value (hb_font_t *font, - hb_position_t &correction_height) const + inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; @@ -302,12 +301,14 @@ struct MathKernInfoRecord return_trace (true); } - inline const MathKern &get_math_kern (hb_ot_math_kern_t kern, - const void *base) const + inline hb_position_t get_kerning (hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font, + const void *base) const { unsigned int idx = kern; - if (unlikely (idx > ARRAY_LENGTH (mathKern))) return Null(MathKern); - return base+mathKern[idx]; + if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; + return (base+mathKern[idx]).get_value (correction_height, font); } protected: @@ -329,11 +330,13 @@ struct MathKernInfo mathKernInfoRecords.sanitize (c, this)); } - inline const MathKernInfoRecord& - get_math_kern_info_record (hb_codepoint_t glyph) const + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const { unsigned int index = (this+mathKernCoverage).get_coverage (glyph); - return mathKernInfoRecords[index]; + return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); } protected: @@ -374,9 +377,11 @@ struct MathGlyphInfo inline bool is_extended_shape (hb_codepoint_t glyph) const { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } - inline const MathKernInfo &get_math_kern_info (void) const { - return this+mathKernInfo; - } + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } protected: /* Offset to MathItalicsCorrectionInfo table - diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6d6cf5bc6..3d87b506a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1348,8 +1348,5 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); - const OT::MathGlyphInfo &glyphInfo = math.get_math_glyph_info(); - const OT::MathKernInfo &kernInfo = glyphInfo.get_math_kern_info(); - const OT::MathKernInfoRecord &kernInfoRecord = kernInfo.get_math_kern_info_record(glyph); - return kernInfoRecord.get_math_kern (kern, &kernInfo).get_value (font, correction_height); + return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } From 8d58e3433e242bd9dd18aa08f55ab0a406583fb0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 13:39:58 +0100 Subject: [PATCH 0055/1326] [MATH] Fix get_kerning() with negative y-scale --- src/hb-ot-layout-math-table.hh | 36 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 4600eab32..7686bf1fc 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -252,20 +252,24 @@ struct MathKern { const MathValueRecord* correctionHeight = mathValueRecords; const MathValueRecord* kernValue = mathValueRecords + heightCount; - // The description of the MathKern table is a ambiguous, but interpreting - // "between the two heights found at those indexes" for 0 < i < len as - // - // correctionHeight[i-1] < correction_height <= correctionHeight[i] - // - // makes the result consistent with the limit cases and we can just use the - // binary search algorithm of std::upper_bound: - unsigned int count = heightCount; + int sign = font->y_scale < 0 ? -1 : +1; + + /* The description of the MathKern table is a ambiguous, but interpreting + * "between the two heights found at those indexes" for 0 < i < len as + * + * correctionHeight[i-1] < correction_height <= correctionHeight[i] + * + * makes the result consistent with the limit cases and we can just use the + * binary search algorithm of std::upper_bound: + */ unsigned int i = 0; - while (count > 0) { + unsigned int count = heightCount; + while (count > 0) + { unsigned int half = count / 2; - hb_position_t height = - correctionHeight[i + half].get_y_value(font, this); - if (height < correction_height) { + hb_position_t height = correctionHeight[i + half].get_y_value(font, this); + if (sign * height < sign * correction_height) + { i += half + 1; count -= half + 1; } else @@ -279,9 +283,11 @@ protected: MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. * Sorted by the height value in - * design units. */ - /* Array of kern values corresponding - * to heights. */ + * design units (heightCount entries), + * Followed by: + * Array of kern values corresponding + * to heights. (heightCount+1 entries). + */ public: DEFINE_SIZE_ARRAY (2, mathValueRecords); From 722e620f20fa2225cf874f4aeb115a064142fcf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Mon, 26 Sep 2016 11:51:36 +0200 Subject: [PATCH 0056/1326] Use G_TEST_DIST to build the path of math test fonts --- test/api/Makefile.am | 2 ++ test/api/test-ot-layout-math.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 322cd7d2a..27520ffe8 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -83,6 +83,8 @@ TESTS_ENVIRONMENT = \ G_DEBUG=gc-friendly \ G_SLICE=always-malloc \ srcdir=$(srcdir) \ + G_TEST_SRCDIR=$(abs_srcdir) \ + G_TEST_BUILDDIR=$(abs_builddir) \ $(NULL) diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c index d7121a2a2..93dab740a 100644 --- a/test/api/test-ot-layout-math.c +++ b/test/api/test-ot-layout-math.c @@ -54,12 +54,16 @@ cleanupFreeType (void) static void openFont(const char* fontFile) { + gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); + FT_Error ft_error; - if ((ft_error = FT_New_Face (ft_library, fontFile, 0, &ft_face))) + if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { + g_free(path); abort(); + } + g_free(path); #define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); From 51da7a1cd672aada84bdbb3a2a8dd77ab1134249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Thu, 25 Aug 2016 11:17:50 +0200 Subject: [PATCH 0057/1326] MATH table: Add API to access math variants. --- src/hb-ot-layout-math-table.hh | 253 +++++++++++++++++++++++- src/hb-ot-layout-private.hh | 10 + src/hb-ot-layout.cc | 54 +++++ test/api/fonts/MathTestFontPartial4.otf | Bin 0 -> 14360 bytes test/api/test-ot-layout-math.c | 51 +++++ 5 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 test/api/fonts/MathTestFontPartial4.otf diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 7686bf1fc..784f5c1a8 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -279,7 +279,7 @@ struct MathKern } protected: - USHORT heightCount; + USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. * Sorted by the height value in @@ -413,6 +413,243 @@ public: DEFINE_SIZE_STATIC (8); }; +struct MathGlyphVariantRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + hb_codepoint_t get_glyph() const { return variantGlyph; } + inline hb_position_t get_advance_measurement (hb_font_t *font, + bool horizontal) const + { + return horizontal ? + font->em_scale_x (advanceMeasurement) : + font->em_scale_y (advanceMeasurement); + } + +protected: + GlyphID variantGlyph; /* Glyph ID for the variant. */ + USHORT advanceMeasurement; /* Advance width/height, in design units, of the + * variant, in the direction of requested + * glyph extension. */ + +public: + DEFINE_SIZE_STATIC (2 + 2); +}; + +struct PartFlags : USHORT +{ + enum Flags { + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + }; + +public: + DEFINE_SIZE_STATIC (2); +}; + +struct GlyphPartRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + hb_codepoint_t get_glyph() const { return glyph; } + + inline hb_position_t + get_start_connector_length (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (startConnectorLength) : + font->em_scale_y (startConnectorLength); + } + + inline hb_position_t + get_end_connector_length (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (endConnectorLength) : + font->em_scale_y (endConnectorLength); + } + + inline hb_position_t + get_full_advance (hb_font_t *font, bool horizontal) const + { + return horizontal ? + font->em_scale_x (fullAdvance) : + font->em_scale_y (fullAdvance); + } + + inline bool is_extender() const { + return partFlags & PartFlags::Flags::Extender; + } + +protected: + GlyphID glyph; /* Glyph ID for the part. */ + USHORT startConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the beginning of the glyph, in the + * direction of the extension. */ + USHORT endConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the end of the glyph, in the direction of + * the extension. */ + USHORT fullAdvance; /* Full advance width/height for this part, + * in the direction of the extension. + * In design units. */ + PartFlags partFlags; /* Part qualifiers. */ + +public: + DEFINE_SIZE_STATIC (5 * 2); +}; + +struct GlyphAssembly +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + italicsCorrection.sanitize(c, this) && + partRecords.sanitize(c)); + } + + inline hb_position_t get_italic_correction (hb_font_t *font) const + { return italicsCorrection.get_x_value(font, this); } + + inline unsigned int part_record_count() const { return partRecords.len; } + inline const GlyphPartRecord &get_part_record(unsigned int i) const { + assert(i < partRecords.len); + return partRecords[i]; + } + +protected: + MathValueRecord italicsCorrection; /* Italics correction of this + * GlyphAssembly. Should not + * depend on the assembly size. */ + ArrayOf partRecords; /* Array of part records, from + * left to right and bottom to + * top. */ + +public: + DEFINE_SIZE_ARRAY (4 + 2, partRecords); +}; + +struct MathGlyphConstruction +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + glyphAssembly.sanitize(c, this) && + mathGlyphVariantRecord.sanitize(c)); + } + + inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; } + inline const GlyphAssembly &get_glyph_assembly (void) const { + return this+glyphAssembly; + } + + inline unsigned int glyph_variant_count() const { + return mathGlyphVariantRecord.len; + } + inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const { + assert(i < mathGlyphVariantRecord.len); + return mathGlyphVariantRecord[i]; + } + +protected: + /* Offset to GlyphAssembly table for this shape - from the beginning of + MathGlyphConstruction table. May be NULL. */ + OffsetTo glyphAssembly; + + /* MathGlyphVariantRecords for alternative variants of the glyphs. */ + ArrayOf mathGlyphVariantRecord; + +public: + DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord); +}; + +struct MathVariants +{ + inline bool sanitize_offsets (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = vertGlyphCount + horizGlyphCount; + for (unsigned int i = 0; i < count; i++) + if (!glyphConstruction[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + vertGlyphCoverage.sanitize (c, this) && + horizGlyphCoverage.sanitize (c, this) && + c->check_array (glyphConstruction, + glyphConstruction[0].static_size, + vertGlyphCount + horizGlyphCount) && + sanitize_offsets (c)); + } + + inline hb_position_t get_min_connector_overlap (hb_font_t *font, + bool horizontal) const + { + return horizontal ? + font->em_scale_x (minConnectorOverlap) : + font->em_scale_y (minConnectorOverlap); + } + + inline bool + get_glyph_construction (hb_codepoint_t glyph, + hb_bool_t horizontal, + const MathGlyphConstruction *&glyph_construction) const { + unsigned int index = + horizontal ? + (this+horizGlyphCoverage).get_coverage (glyph) : + (this+vertGlyphCoverage).get_coverage (glyph); + if (likely (index == NOT_COVERED)) return false; + + USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount; + if (unlikely (index >= glyphCount)) return false; + + if (horizontal) + index += vertGlyphCount; + + glyph_construction = &(this + glyphConstruction[index]); + return true; + } + +protected: + USHORT minConnectorOverlap; /* Minimum overlap of connecting + * glyphs during glyph construction, + * in design units. */ + OffsetTo vertGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + OffsetTo horizGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + USHORT vertGlyphCount; /* Number of glyphs for which + * information is provided for + * vertically growing variants. */ + USHORT horizGlyphCount; /* Number of glyphs for which + * information is provided for + * horizontally growing variants. */ + + /* Array of offsets to MathGlyphConstruction tables - from the beginning of + the MathVariants table, for shapes growing in vertical/horizontal + direction. */ + OffsetTo glyphConstruction[VAR]; + +public: + DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction); +}; + /* * MATH -- The MATH Table @@ -428,24 +665,32 @@ struct MATH return_trace (version.sanitize (c) && likely (version.major == 1) && mathConstants.sanitize (c, this) && - mathGlyphInfo.sanitize (c, this)); + mathGlyphInfo.sanitize (c, this) && + mathVariants.sanitize (c, this)); } inline hb_position_t get_constant (hb_ot_math_constant_t constant, - hb_font_t *font) const + hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } inline const MathGlyphInfo &get_math_glyph_info (void) const { return this+mathGlyphInfo; } + + inline bool has_math_variants (void) const { return mathVariants != 0; } + inline const MathVariants &get_math_variants (void) const { + return this+mathVariants; + } + protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants;/* MathConstants table */ OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ + OffsetTo mathVariants; /* MathVariants table */ public: - DEFINE_SIZE_STATIC (8); + DEFINE_SIZE_STATIC (10); }; } /* mathspace OT */ diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index a4272de63..775261a49 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -617,5 +617,15 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props +namespace OT { + struct MathGlyphConstruction; +}; + +HB_INTERNAL hb_bool_t +hb_ot_layout_get_math_glyph_construction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal, + hb_position_t &minConnectorOverlap, + const OT::MathGlyphConstruction *&glyph_construction); #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3d87b506a..e92d38b0b 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1350,3 +1350,57 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, const OT::MATH &math = _get_math (font->face); return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } + +#if 0 +/** + * hb_ot_layout_get_math_italic_correction_for_glyph_assembly: + * @font: an #hb_font_t with an OpenType MATH table + * @base_glyph: index of the glyph to stretch + * @horizontal: direction of the stretching + * + * This function tries and get the italic correction associated to the glyph + * assembly used to stretch the base glyph in the specified direction. + * + * Return value: the italic correction of the glyph assembly or 0 + * + * Since: ???? + **/ +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font, + hb_codepoint_t base_glyph, + hb_bool_t horizontal) +{ + const OT::MATH &math = _get_math (font->face); + + if (math.has_math_variants()) { + const OT::MathGlyphConstruction* glyph_construction; + if (math.get_math_variants(). + get_glyph_construction(base_glyph, horizontal, glyph_construction) && + glyph_construction->has_glyph_assembly()) + return glyph_construction-> + get_glyph_assembly().get_italic_correction(font); + } + + return 0; +} + +HB_INTERNAL hb_bool_t +hb_ot_layout_get_math_glyph_construction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal, + hb_position_t &minConnectorOverlap, + const OT::MathGlyphConstruction *&glyph_construction) +{ + const OT::MATH &math = _get_math (font->face); + + if (!math.has_math_variants()) return false; + + const OT::MathVariants &mathVariants = math.get_math_variants(); + if (!mathVariants.get_glyph_construction(glyph, horizontal, + glyph_construction)) return false; + + minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal); + + return true; +} +#endif diff --git a/test/api/fonts/MathTestFontPartial4.otf b/test/api/fonts/MathTestFontPartial4.otf new file mode 100644 index 0000000000000000000000000000000000000000..cda3057f8360d61154b3fad650c77e413e3d97f0 GIT binary patch literal 14360 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 OKcR?G6mRw~ Date: Mon, 26 Sep 2016 16:10:08 +0100 Subject: [PATCH 0058/1326] [MATH] Clean up math variants --- src/hb-ot-layout-math-table.hh | 35 +++++++++------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 784f5c1a8..bec53f36d 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -437,7 +437,7 @@ protected: * glyph extension. */ public: - DEFINE_SIZE_STATIC (2 + 2); + DEFINE_SIZE_STATIC (4); }; struct PartFlags : USHORT @@ -504,7 +504,7 @@ protected: PartFlags partFlags; /* Part qualifiers. */ public: - DEFINE_SIZE_STATIC (5 * 2); + DEFINE_SIZE_STATIC (10); }; struct GlyphAssembly @@ -522,7 +522,6 @@ struct GlyphAssembly inline unsigned int part_record_count() const { return partRecords.len; } inline const GlyphPartRecord &get_part_record(unsigned int i) const { - assert(i < partRecords.len); return partRecords[i]; } @@ -535,7 +534,7 @@ protected: * top. */ public: - DEFINE_SIZE_ARRAY (4 + 2, partRecords); + DEFINE_SIZE_ARRAY (6, partRecords); }; struct MathGlyphConstruction @@ -548,19 +547,6 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } - inline bool has_glyph_assembly (void) const { return glyphAssembly != 0; } - inline const GlyphAssembly &get_glyph_assembly (void) const { - return this+glyphAssembly; - } - - inline unsigned int glyph_variant_count() const { - return mathGlyphVariantRecord.len; - } - inline const MathGlyphVariantRecord &get_glyph_variant(unsigned int i) const { - assert(i < mathGlyphVariantRecord.len); - return mathGlyphVariantRecord[i]; - } - protected: /* Offset to GlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ @@ -570,7 +556,7 @@ protected: ArrayOf mathGlyphVariantRecord; public: - DEFINE_SIZE_ARRAY (2 + 2, mathGlyphVariantRecord); + DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); }; struct MathVariants @@ -647,7 +633,7 @@ protected: OffsetTo glyphConstruction[VAR]; public: - DEFINE_SIZE_ARRAY (5 * 2, glyphConstruction); + DEFINE_SIZE_ARRAY (10, glyphConstruction); }; @@ -673,14 +659,11 @@ struct MATH hb_font_t *font) const { return (this+mathConstants).get_value (constant, font); } - inline const MathGlyphInfo &get_math_glyph_info (void) const { - return this+mathGlyphInfo; - } + inline const MathGlyphInfo &get_math_glyph_info (void) const + { return this+mathGlyphInfo; } - inline bool has_math_variants (void) const { return mathVariants != 0; } - inline const MathVariants &get_math_variants (void) const { - return this+mathVariants; - } + inline const MathVariants &get_math_variants (void) const + { return this+mathVariants; } protected: FixedVersion<>version; /* Version of the MATH table From 7fe0e28c22331a353d396f8bc1e3a60f1580a96d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 17:51:47 +0100 Subject: [PATCH 0059/1326] [MATH] Start fleshing out glyph variant API --- src/hb-font-private.hh | 4 ++ src/hb-ot-layout-math-table.hh | 10 ++--- src/hb-ot-layout.cc | 75 ++++++++++++---------------------- src/hb-ot-layout.h | 20 +++++++++ src/hb-ot-math.h | 18 ++++++++ 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 0b7557794..07bc90093 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -118,6 +118,10 @@ struct hb_font_t { /* Convert from font-space to user-space */ inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) + { return em_scale (v, + HB_DIRECTION_IS_VERTICAL(direction) ? + this->y_scale : this->x_scale); } /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index bec53f36d..81fc1b009 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -582,13 +582,9 @@ struct MathVariants sanitize_offsets (c)); } - inline hb_position_t get_min_connector_overlap (hb_font_t *font, - bool horizontal) const - { - return horizontal ? - font->em_scale_x (minConnectorOverlap) : - font->em_scale_y (minConnectorOverlap); - } + inline hb_position_t get_min_connector_overlap (hb_direction_t direction, + hb_font_t *font) const + { return font->em_scale_dir (minConnectorOverlap, direction); } inline bool get_glyph_construction (hb_codepoint_t glyph, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index e92d38b0b..eeebb5d77 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1279,7 +1279,7 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_italics_correction (hb_font_t *font, hb_codepoint_t glyph) { @@ -1297,7 +1297,7 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, hb_codepoint_t glyph) { @@ -1315,7 +1315,7 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * * Since: 1.4 **/ -HB_EXTERN hb_bool_t +hb_bool_t hb_ot_layout_is_math_extended_shape (hb_face_t *face, hb_codepoint_t glyph) { @@ -1351,56 +1351,35 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } -#if 0 -/** - * hb_ot_layout_get_math_italic_correction_for_glyph_assembly: - * @font: an #hb_font_t with an OpenType MATH table - * @base_glyph: index of the glyph to stretch - * @horizontal: direction of the stretching - * - * This function tries and get the italic correction associated to the glyph - * assembly used to stretch the base glyph in the specified direction. - * - * Return value: the italic correction of the glyph assembly or 0 - * - * Since: ???? - **/ -HB_EXTERN hb_position_t -hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font_t *font, - hb_codepoint_t base_glyph, - hb_bool_t horizontal) +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variant_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); - - if (math.has_math_variants()) { - const OT::MathGlyphConstruction* glyph_construction; - if (math.get_math_variants(). - get_glyph_construction(base_glyph, horizontal, glyph_construction) && - glyph_construction->has_glyph_assembly()) - return glyph_construction-> - get_glyph_assembly().get_italic_correction(font); - } - return 0; } -HB_INTERNAL hb_bool_t -hb_ot_layout_get_math_glyph_construction (hb_font_t *font, - hb_codepoint_t glyph, - hb_bool_t horizontal, - hb_position_t &minConnectorOverlap, - const OT::MathGlyphConstruction *&glyph_construction) +hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction) { const OT::MATH &math = _get_math (font->face); - - if (!math.has_math_variants()) return false; - - const OT::MathVariants &mathVariants = math.get_math_variants(); - if (!mathVariants.get_glyph_construction(glyph, horizontal, - glyph_construction)) return false; - - minConnectorOverlap = mathVariants.get_min_connector_overlap(font, horizontal); - - return true; + return math.get_math_variants().get_min_connector_overlap (direction, font); +} + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italic_correction /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return 0; } -#endif diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 9c1c57bb4..8eb8d6cbd 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -328,6 +328,26 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, hb_ot_math_kern_t kern, hb_position_t correction_height); +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variant_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italic_correction /* OUT */); HB_END_DECLS diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index a62b4b612..bf37975d2 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -102,6 +102,24 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; +typedef struct hb_math_glyph_variant_t { + hb_codepoint_t glyph; + hb_position_t advance; +} hb_math_glyph_variant_t; + +typedef enum { /*< flags >*/ + HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ +} hb_math_glyph_part_flags_t; + +typedef struct hb_math_glyph_part_t { + hb_codepoint_t glyph; + hb_position_t start_connector_length; + hb_position_t end_connector_length; + hb_position_t full_advance; + hb_math_glyph_part_flags_t flags; +} hb_math_glyph_part_t; + + HB_END_DECLS #endif /* HB_OT_MATH_H */ From 353f455af7ccbc1af8338dcb0c8ab87aef866c79 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:22:48 +0200 Subject: [PATCH 0060/1326] [MATH] Wire up get_glyph_variants() --- src/hb-font-private.hh | 11 +- src/hb-ot-layout-math-table.hh | 178 ++++++++++++++++----------------- src/hb-ot-layout.cc | 7 +- src/hb-ot-layout.h | 2 +- 4 files changed, 95 insertions(+), 103 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 07bc90093..6d5012ec1 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -116,12 +116,12 @@ struct hb_font_t { /* Convert from font-space to user-space */ - inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } - inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } + inline int dir_scale (hb_direction_t direction) + { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } + inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } + inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) - { return em_scale (v, - HB_DIRECTION_IS_VERTICAL(direction) ? - this->y_scale : this->x_scale); } + { return em_scale (v, dir_scale (direction)); } /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { @@ -508,7 +508,6 @@ struct hb_font_t { return false; } - private: inline hb_position_t em_scale (int16_t v, int scale) { int upem = face->get_upem (); diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 81fc1b009..da65c3886 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -47,13 +47,13 @@ struct MathValueRecord return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); } -protected: + protected: SHORT value; /* The X or Y value in design units */ OffsetTo deviceTable; /* Offset to the device table - from the * beginning of parent table. May be NULL. * Suggested format for device table is 1. */ -public: + public: DEFINE_SIZE_STATIC (4); }; @@ -153,13 +153,13 @@ struct MathConstants } } -protected: + protected: SHORT percentScaleDown[2]; USHORT minHeight[2]; MathValueRecord mathValueRecords[51]; SHORT radicalDegreeBottomRaisePercent; -public: + public: DEFINE_SIZE_STATIC (214); }; @@ -180,7 +180,7 @@ struct MathItalicsCorrectionInfo return italicsCorrection[index].get_x_value (font, this); } -protected: + protected: OffsetTo coverage; /* Offset to Coverage table - * from the beginning of * MathItalicsCorrectionInfo @@ -190,7 +190,7 @@ protected: * values for each * covered glyph. */ -public: + public: DEFINE_SIZE_ARRAY (4, italicsCorrection); }; @@ -213,7 +213,7 @@ struct MathTopAccentAttachment return topAccentAttachment[index].get_x_value(font, this); } -protected: + protected: OffsetTo topAccentCoverage; /* Offset to Coverage table - * from the beginning of * MathTopAccentAttachment @@ -223,7 +223,7 @@ protected: * attachment points for each * covered glyph. */ -public: + public: DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); }; @@ -278,7 +278,7 @@ struct MathKern return kernValue[i].get_x_value(font, this); } -protected: + protected: USHORT heightCount; MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at * which the kern value changes. @@ -289,7 +289,7 @@ protected: * to heights. (heightCount+1 entries). */ -public: + public: DEFINE_SIZE_ARRAY (2, mathValueRecords); }; @@ -317,12 +317,12 @@ struct MathKernInfoRecord return (base+mathKern[idx]).get_value (correction_height, font); } -protected: + protected: /* Offset to MathKern table for each corner - * from the beginning of MathKernInfo table. May be NULL. */ OffsetTo mathKern[4]; -public: + public: DEFINE_SIZE_STATIC (8); }; @@ -345,7 +345,7 @@ struct MathKernInfo return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); } -protected: + protected: OffsetTo mathKernCoverage; /* Offset to Coverage table - * from the beginning of the * MathKernInfo table. */ @@ -356,7 +356,7 @@ protected: * of subscripts and * superscripts. */ -public: + public: DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); }; @@ -389,7 +389,7 @@ struct MathGlyphInfo hb_font_t *font) const { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } -protected: + protected: /* Offset to MathItalicsCorrectionInfo table - * from the beginning of MathGlyphInfo table. */ OffsetTo mathItalicsCorrectionInfo; @@ -409,34 +409,27 @@ protected: * from the beginning of MathGlyphInfo table. */ OffsetTo mathKernInfo; -public: + public: DEFINE_SIZE_STATIC (8); }; struct MathGlyphVariantRecord { + friend struct MathGlyphConstruction; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - hb_codepoint_t get_glyph() const { return variantGlyph; } - inline hb_position_t get_advance_measurement (hb_font_t *font, - bool horizontal) const - { - return horizontal ? - font->em_scale_x (advanceMeasurement) : - font->em_scale_y (advanceMeasurement); - } - -protected: + protected: GlyphID variantGlyph; /* Glyph ID for the variant. */ USHORT advanceMeasurement; /* Advance width/height, in design units, of the * variant, in the direction of requested * glyph extension. */ -public: + public: DEFINE_SIZE_STATIC (4); }; @@ -446,49 +439,21 @@ struct PartFlags : USHORT Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ }; -public: + public: DEFINE_SIZE_STATIC (2); }; -struct GlyphPartRecord +struct MathGlyphPartRecord { + friend struct MathGlyphAssembly; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } - hb_codepoint_t get_glyph() const { return glyph; } - - inline hb_position_t - get_start_connector_length (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (startConnectorLength) : - font->em_scale_y (startConnectorLength); - } - - inline hb_position_t - get_end_connector_length (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (endConnectorLength) : - font->em_scale_y (endConnectorLength); - } - - inline hb_position_t - get_full_advance (hb_font_t *font, bool horizontal) const - { - return horizontal ? - font->em_scale_x (fullAdvance) : - font->em_scale_y (fullAdvance); - } - - inline bool is_extender() const { - return partFlags & PartFlags::Flags::Extender; - } - -protected: + protected: GlyphID glyph; /* Glyph ID for the part. */ USHORT startConnectorLength; /* Advance width/ height of the straight bar * connector material, in design units, is at @@ -503,11 +468,11 @@ protected: * In design units. */ PartFlags partFlags; /* Part qualifiers. */ -public: + public: DEFINE_SIZE_STATIC (10); }; -struct GlyphAssembly +struct MathGlyphAssembly { inline bool sanitize (hb_sanitize_context_t *c) const { @@ -520,20 +485,15 @@ struct GlyphAssembly inline hb_position_t get_italic_correction (hb_font_t *font) const { return italicsCorrection.get_x_value(font, this); } - inline unsigned int part_record_count() const { return partRecords.len; } - inline const GlyphPartRecord &get_part_record(unsigned int i) const { - return partRecords[i]; - } - -protected: + protected: MathValueRecord italicsCorrection; /* Italics correction of this - * GlyphAssembly. Should not + * MathGlyphAssembly. Should not * depend on the assembly size. */ - ArrayOf partRecords; /* Array of part records, from + ArrayOf partRecords; /* Array of part records, from * left to right and bottom to * top. */ -public: + public: DEFINE_SIZE_ARRAY (6, partRecords); }; @@ -547,15 +507,36 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } -protected: - /* Offset to GlyphAssembly table for this shape - from the beginning of + inline unsigned int get_variants (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) const + { + if (variants_count) + { + int scale = font->dir_scale (direction); + const MathGlyphVariantRecord *arr = + mathGlyphVariantRecord.sub_array (start_offset, variants_count); + unsigned int count = *variants_count; + for (unsigned int i = 0; i < count; i++) + { + variants[i].glyph = arr[i].variantGlyph; + variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); + } + } + return mathGlyphVariantRecord.len; + } + + protected: + /* Offset to MathGlyphAssembly table for this shape - from the beginning of MathGlyphConstruction table. May be NULL. */ - OffsetTo glyphAssembly; + OffsetTo glyphAssembly; /* MathGlyphVariantRecords for alternative variants of the glyphs. */ ArrayOf mathGlyphVariantRecord; -public: + public: DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); }; @@ -586,27 +567,36 @@ struct MathVariants hb_font_t *font) const { return font->em_scale_dir (minConnectorOverlap, direction); } - inline bool - get_glyph_construction (hb_codepoint_t glyph, - hb_bool_t horizontal, - const MathGlyphConstruction *&glyph_construction) const { - unsigned int index = - horizontal ? - (this+horizGlyphCoverage).get_coverage (glyph) : - (this+vertGlyphCoverage).get_coverage (glyph); - if (likely (index == NOT_COVERED)) return false; + inline unsigned int get_glyph_variants (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_variants (direction, font, start_offset, variants_count, variants); } - USHORT glyphCount = horizontal ? horizGlyphCount : vertGlyphCount; - if (unlikely (index >= glyphCount)) return false; + private: + inline const MathGlyphConstruction & + get_glyph_construction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font) const + { + bool vertical = HB_DIRECTION_IS_VERTICAL (direction); + unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; + const OffsetTo &coverage = vertical ? vertGlyphCoverage + : horizGlyphCoverage; - if (horizontal) + unsigned int index = (this+coverage).get_coverage (glyph); + if (unlikely (index >= count)) return Null(MathGlyphConstruction); + + if (!vertical) index += vertGlyphCount; - glyph_construction = &(this + glyphConstruction[index]); - return true; + return this+glyphConstruction[index]; } -protected: + protected: USHORT minConnectorOverlap; /* Minimum overlap of connecting * glyphs during glyph construction, * in design units. */ @@ -626,9 +616,9 @@ protected: /* Array of offsets to MathGlyphConstruction tables - from the beginning of the MathVariants table, for shapes growing in vertical/horizontal direction. */ - OffsetTo glyphConstruction[VAR]; + OffsetTo glyphConstruction[VAR]; -public: + public: DEFINE_SIZE_ARRAY (10, glyphConstruction); }; @@ -661,14 +651,14 @@ struct MATH inline const MathVariants &get_math_variants (void) const { return this+mathVariants; } -protected: + protected: FixedVersion<>version; /* Version of the MATH table * initially set to 0x00010000u */ OffsetTo mathConstants;/* MathConstants table */ OffsetTo mathGlyphInfo;/* MathGlyphInfo table */ OffsetTo mathVariants; /* MathVariants table */ -public: + public: DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index eeebb5d77..0d3f19bef 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1356,11 +1356,14 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, unsigned int start_offset, - unsigned int *variant_count, /* IN/OUT */ + unsigned int *variants_count, /* IN/OUT */ hb_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); - return 0; + return math.get_math_variants().get_glyph_variants (glyph, direction, font, + start_offset, + variants_count, + variants); } hb_position_t diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 8eb8d6cbd..4c01d6310 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -333,7 +333,7 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, unsigned int start_offset, - unsigned int *variant_count, /* IN/OUT */ + unsigned int *variants_count, /* IN/OUT */ hb_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t From 559eb564472575ae4d87a241314b8a3ca24418c4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:46:05 +0200 Subject: [PATCH 0061/1326] [MATH] Wire up get_glyph_assembly() --- src/hb-ot-layout-math-table.hh | 64 +++++++++++++++++++++++++++++++--- src/hb-ot-layout.cc | 26 ++++++++------ src/hb-ot-layout.h | 14 ++++---- 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index da65c3886..886ed2dca 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -436,7 +436,9 @@ struct MathGlyphVariantRecord struct PartFlags : USHORT { enum Flags { - Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + + Defined = 0x0001u, /* All defined flags. */ }; public: @@ -445,14 +447,30 @@ struct PartFlags : USHORT struct MathGlyphPartRecord { - friend struct MathGlyphAssembly; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } + inline void extract (hb_math_glyph_part_t &out, + int scale, + hb_font_t *font) const + { + out.glyph = glyph; + + out.start_connector_length = font->em_scale (startConnectorLength, scale); + out.end_connector_length = font->em_scale (endConnectorLength, scale); + out.full_advance = font->em_scale (fullAdvance, scale); + + ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == + (unsigned int) PartFlags::Extender); + + out.flags = (hb_math_glyph_part_flags_t) + (unsigned int) + (partFlags & PartFlags::Defined); + } + protected: GlyphID glyph; /* Glyph ID for the part. */ USHORT startConnectorLength; /* Advance width/ height of the straight bar @@ -482,8 +500,28 @@ struct MathGlyphAssembly partRecords.sanitize(c)); } - inline hb_position_t get_italic_correction (hb_font_t *font) const - { return italicsCorrection.get_x_value(font, this); } + inline unsigned int get_parts (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { + if (parts_count) + { + int scale = font->dir_scale (direction); + const MathGlyphPartRecord *arr = + partRecords.sub_array (start_offset, parts_count); + unsigned int count = *parts_count; + for (unsigned int i = 0; i < count; i++) + arr[i].extract (parts[i], scale, font); + } + + if (italics_correction) + *italics_correction = italicsCorrection.get_x_value (font, this); + + return partRecords.len; + } protected: MathValueRecord italicsCorrection; /* Italics correction of this @@ -507,6 +545,9 @@ struct MathGlyphConstruction mathGlyphVariantRecord.sanitize(c)); } + inline const MathGlyphAssembly &get_assembly (void) const + { return this+glyphAssembly; } + inline unsigned int get_variants (hb_direction_t direction, hb_font_t *font, unsigned int start_offset, @@ -576,6 +617,19 @@ struct MathVariants { return get_glyph_construction (glyph, direction, font) .get_variants (direction, font, start_offset, variants_count, variants); } + inline unsigned int get_glyph_parts (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_assembly () + .get_parts (direction, font, + start_offset, parts_count, parts, + italics_correction); } + private: inline const MathGlyphConstruction & get_glyph_construction (hb_codepoint_t glyph, diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0d3f19bef..942158e80 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1341,7 +1341,7 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * * Since: 1.4 **/ -HB_EXTERN hb_position_t +hb_position_t hb_ot_layout_get_math_kerning (hb_font_t *font, hb_codepoint_t glyph, hb_ot_math_kern_t kern, @@ -1351,7 +1351,7 @@ hb_ot_layout_get_math_kerning (hb_font_t *font, return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } -HB_EXTERN unsigned int +unsigned int hb_ot_layout_get_math_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, hb_direction_t direction, @@ -1374,15 +1374,19 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, return math.get_math_variants().get_min_connector_overlap (direction, font); } -HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italic_correction /* OUT */) +unsigned int +hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */) { const OT::MATH &math = _get_math (font->face); - return 0; + return math.get_math_variants().get_glyph_parts (glyph, direction, font, + start_offset, + parts_count, + parts, + italics_correction); } diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 4c01d6310..b6fbd00a5 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -341,13 +341,13 @@ hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, hb_direction_t direction); HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly_parts (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italic_correction /* OUT */); +hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); HB_END_DECLS From 97b72da6006d8d6355ee90d514f627e6604a4936 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:53:25 +0200 Subject: [PATCH 0062/1326] Whitespace --- src/hb-ot-layout-math-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index 886ed2dca..efffd2b53 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -514,7 +514,7 @@ struct MathGlyphAssembly partRecords.sub_array (start_offset, parts_count); unsigned int count = *parts_count; for (unsigned int i = 0; i < count; i++) - arr[i].extract (parts[i], scale, font); + arr[i].extract (parts[i], scale, font); } if (italics_correction) From 1ba767cd4e3606beb9dc59806b83b1e61f5958d4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 21:57:14 +0200 Subject: [PATCH 0063/1326] [MATH] Move API from hb-ot-layout.h to hb-ot-math.h --- src/hb-ot-layout.h | 52 ------------------------------------------ src/hb-ot-math.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++ src/hb-ot.h | 1 + 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index b6fbd00a5..eb23d45b6 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -33,7 +33,6 @@ #include "hb.h" -#include "hb-ot-math.h" #include "hb-ot-tag.h" HB_BEGIN_DECLS @@ -43,7 +42,6 @@ HB_BEGIN_DECLS #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') -#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') /* @@ -299,56 +297,6 @@ hb_ot_layout_get_size_params (hb_face_t *face, unsigned int *range_end /* OUT. May be NULL */); -/* - * MATH - */ - -HB_EXTERN hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); - -HB_EXTERN hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_variants (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */); - -HB_EXTERN hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */); - HB_END_DECLS #endif /* HB_OT_LAYOUT_H */ diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index bf37975d2..5ff19fd24 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -36,6 +36,14 @@ HB_BEGIN_DECLS +/* + * MATH + */ + +#define HB_OT_TAG_MATH HB_TAG('M','A','T','H') + +/* Types */ + typedef enum { HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, @@ -119,6 +127,54 @@ typedef struct hb_math_glyph_part_t { hb_math_glyph_part_flags_t flags; } hb_math_glyph_part_t; +/* Methods */ + +HB_EXTERN hb_bool_t +hb_ot_layout_has_math_data (hb_face_t *face); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_constant (hb_font_t *font, + hb_ot_math_constant_t constant); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); + +HB_EXTERN hb_bool_t +hb_ot_layout_is_math_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */); + +HB_EXTERN hb_position_t +hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); + +HB_EXTERN unsigned int +hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); + HB_END_DECLS diff --git a/src/hb-ot.h b/src/hb-ot.h index 47c92a58e..113e37b08 100644 --- a/src/hb-ot.h +++ b/src/hb-ot.h @@ -32,6 +32,7 @@ #include "hb-ot-font.h" #include "hb-ot-layout.h" +#include "hb-ot-math.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" From 86106c7528d9bff8de6bc3e1487be780c31ea4fd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 22:12:48 +0200 Subject: [PATCH 0064/1326] [MATH] Rename all API to hb_ot_math_* --- src/hb-ot-layout-private.hh | 10 - src/hb-ot-layout.cc | 69 +++--- src/hb-ot-math.h | 58 ++--- test/api/Makefile.am | 6 +- test/api/test-ot-layout-math.c | 382 --------------------------------- test/api/test-ot-math.c | 381 ++++++++++++++++++++++++++++++++ 6 files changed, 448 insertions(+), 458 deletions(-) delete mode 100644 test/api/test-ot-layout-math.c create mode 100644 test/api/test-ot-math.c diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 775261a49..a4272de63 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -617,15 +617,5 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props -namespace OT { - struct MathGlyphConstruction; -}; - -HB_INTERNAL hb_bool_t -hb_ot_layout_get_math_glyph_construction (hb_font_t *font, - hb_codepoint_t glyph, - hb_bool_t horizontal, - hb_position_t &minConnectorOverlap, - const OT::MathGlyphConstruction *&glyph_construction); #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 942158e80..588f5ab00 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1225,9 +1225,10 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, /* * MATH */ +/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */ /** - * hb_ot_layout_has_math_data: + * hb_ot_math_has_data: * * @face: #hb_face_t to test * @@ -1240,13 +1241,13 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * Since: 1.4 **/ hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face) +hb_ot_math_has_data (hb_face_t *face) { return &_get_math (face) != &OT::Null(OT::MATH); } /** - * hb_ot_layout_get_math_constant: + * hb_ot_math_get_constant: * * @font: #hb_font_t from which to retrieve the value * @constant: #hb_ot_math_constant_t the constant to retrieve @@ -1262,15 +1263,15 @@ hb_ot_layout_has_math_data (hb_face_t *face) * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant) +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant) { const OT::MATH &math = _get_math (font->face); return math.get_constant(constant, font); } /** - * hb_ot_layout_get_math_italics_correction: + * hb_ot_math_get_glyph_italics_correction: * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value @@ -1280,15 +1281,15 @@ hb_ot_layout_get_math_constant (hb_font_t *font, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph) +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); return math.get_math_glyph_info().get_italics_correction (glyph, font); } /** - * hb_ot_layout_get_math_top_accent_attachment: + * hb_ot_math_get_glyph_top_accent_attachment: * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value @@ -1298,15 +1299,15 @@ hb_ot_layout_get_math_italics_correction (hb_font_t *font, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph) +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (font->face); return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); } /** - * hb_ot_layout_is_math_extended_shape: + * hb_ot_math_is_glyph_extended_shape: * * @font: a #hb_font_t to test * @glyph: a glyph index to test @@ -1316,15 +1317,15 @@ hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, * Since: 1.4 **/ hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph) +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) { const OT::MATH &math = _get_math (face); return math.get_math_glyph_info().is_extended_shape (glyph); } /** - * hb_ot_layout_get_math_kerning: + * hb_ot_math_get_glyph_kerning: * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value @@ -1342,22 +1343,22 @@ hb_ot_layout_is_math_extended_shape (hb_face_t *face, * Since: 1.4 **/ hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height) +hb_ot_math_get_glyph_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) { const OT::MATH &math = _get_math (font->face); return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } unsigned int -hb_ot_layout_get_math_glyph_variants (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) +hb_ot_math_get_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); return math.get_math_variants().get_glyph_variants (glyph, direction, font, @@ -1367,21 +1368,21 @@ hb_ot_layout_get_math_glyph_variants (hb_font_t *font, } hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction) +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction) { const OT::MATH &math = _get_math (font->face); return math.get_math_variants().get_min_connector_overlap (direction, font); } unsigned int -hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */) +hb_ot_math_get_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */) { const OT::MATH &math = _get_math (font->face); return math.get_math_variants().get_glyph_parts (glyph, direction, font, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 5ff19fd24..ad8bf14e5 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -130,50 +130,50 @@ typedef struct hb_math_glyph_part_t { /* Methods */ HB_EXTERN hb_bool_t -hb_ot_layout_has_math_data (hb_face_t *face); +hb_ot_math_has_data (hb_face_t *face); HB_EXTERN hb_position_t -hb_ot_layout_get_math_constant (hb_font_t *font, - hb_ot_math_constant_t constant); +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant); HB_EXTERN hb_position_t -hb_ot_layout_get_math_italics_correction (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_position_t -hb_ot_layout_get_math_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph); +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph); HB_EXTERN hb_bool_t -hb_ot_layout_is_math_extended_shape (hb_face_t *face, - hb_codepoint_t glyph); +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph); HB_EXTERN hb_position_t -hb_ot_layout_get_math_kerning (hb_font_t *font, +hb_ot_math_get_glyph_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height); + +HB_EXTERN unsigned int +hb_ot_math_get_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height); - -HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_variants (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */); + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t -hb_ot_layout_get_math_min_connector_overlap (hb_font_t *font, - hb_direction_t direction); +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction); HB_EXTERN unsigned int -hb_ot_layout_get_math_glyph_assembly (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */); +hb_ot_math_get_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */); HB_END_DECLS diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 27520ffe8..58f49146a 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -50,10 +50,10 @@ TEST_PROGS += \ if HAVE_FREETYPE TEST_PROGS += \ - test-ot-layout-math \ + test-ot-math \ $(NULL) -test_ot_layout_math_LDADD = $(LDADD) $(FREETYPE_LIBS) -test_ot_layout_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) +test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS) +test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) endif # HAVE_FREETYPE endif # HAVE_OT diff --git a/test/api/test-ot-layout-math.c b/test/api/test-ot-layout-math.c deleted file mode 100644 index 34ed0fc06..000000000 --- a/test/api/test-ot-layout-math.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright © 2016 Igalia S.L. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Igalia Author(s): Frédéric Wang - */ - - -#include "hb-test.h" - -#include "hb-ft.h" -#include "hb-ot.h" - -/* Unit tests for hb-ot-layout.h - OpenType MATH table */ - -static FT_Library ft_library; -static FT_Face ft_face; -static hb_font_t *hb_font; -static hb_face_t *hb_face; - -static inline void -initFreeType (void) -{ - FT_Error ft_error; - if ((ft_error = FT_Init_FreeType (&ft_library))) - abort(); -} - -static inline void -cleanupFreeType (void) -{ - FT_Done_FreeType (ft_library); -} - -static void -openFont(const char* fontFile) -{ - gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); - - FT_Error ft_error; - if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { - g_free(path); - abort(); - } - g_free(path); - -#define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) - abort(); - hb_font = hb_ft_font_create (ft_face, NULL); - hb_face = hb_ft_face_create_cached(ft_face); -} - -static inline void -closeFont (void) -{ - hb_font_destroy (hb_font); - FT_Done_Face (ft_face); -} - -static void -test_has_math_data (void) -{ - initFreeType(); - - openFont("fonts/MathTestFontNone.otf"); - g_assert(!hb_ot_layout_has_math_data (hb_face)); // MATH table not available - closeFont(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_ot_layout_has_math_data (hb_face)); // MATH table available - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_constant (void) -{ - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert_cmpint(hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); - g_assert_cmpint((hb_ot_layout_get_math_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_italics_correction (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. - g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 197); - g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 150); - g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italics_correction (hb_font, glyph), ==, 452); - closeFont(); - - cleanupFreeType(); - -} - -static void -test_get_math_top_accent_attachment (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. - g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 374); - g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 346); - g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_top_accent_attachment (hb_font, glyph), ==, 318); - closeFont(); - - cleanupFreeType(); -} - -static void -test_is_math_extended_shape (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); // MathGlyphInfo empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); - g_assert(!hb_ot_layout_is_math_extended_shape (hb_face, glyph)); - g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); - g_assert(hb_ot_layout_is_math_extended_shape (hb_face, glyph)); - closeFont(); - - cleanupFreeType(); -} - -static void -test_get_math_kerning (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty - closeFont(); - - openFont("fonts/MathTestFontPartial3.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); - - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height - - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right - g_assert_cmpint(hb_ot_layout_get_math_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left - - closeFont(); - - cleanupFreeType(); -} - - -#if 0 -static void -test_get_math_italic_correction_for_glyph_assembly (void) -{ - hb_codepoint_t glyph; - initFreeType(); - - openFont("fonts/MathTestFontEmpty.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available - closeFont(); - - openFont("fonts/MathTestFontPartial1.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - closeFont(); - - openFont("fonts/MathTestFontPartial2.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - closeFont(); - - openFont("fonts/MathTestFontPartial3.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - closeFont(); - - openFont("fonts/MathTestFontPartial4.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); - closeFont(); - - openFont("fonts/MathTestFontFull.otf"); - g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); - g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); - closeFont(); - - cleanupFreeType(); -} -#endif - -int -main (int argc, char **argv) -{ - hb_test_init (&argc, &argv); - - hb_test_add (test_has_math_data); - hb_test_add (test_get_math_constant); - hb_test_add (test_get_math_italics_correction); - hb_test_add (test_get_math_top_accent_attachment); - hb_test_add (test_is_math_extended_shape); - hb_test_add (test_get_math_kerning); - //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); - - return hb_test_run(); -} diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c new file mode 100644 index 000000000..23c19eff3 --- /dev/null +++ b/test/api/test-ot-math.c @@ -0,0 +1,381 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + + +#include "hb-test.h" + +#include "hb-ft.h" +#include "hb-ot.h" + +/* Unit tests for hb-ot-math.h - OpenType MATH table */ + +static FT_Library ft_library; +static FT_Face ft_face; +static hb_font_t *hb_font; +static hb_face_t *hb_face; + +static inline void +initFreeType (void) +{ + FT_Error ft_error; + if ((ft_error = FT_Init_FreeType (&ft_library))) + abort(); +} + +static inline void +cleanupFreeType (void) +{ + FT_Done_FreeType (ft_library); +} + +static void +openFont(const char* fontFile) +{ + gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); + + FT_Error ft_error; + if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { + g_free(path); + abort(); + } + g_free(path); + +#define fontSize 1000 + if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) + abort(); + hb_font = hb_ft_font_create (ft_face, NULL); + hb_face = hb_ft_face_create_cached(ft_face); +} + +static inline void +closeFont (void) +{ + hb_font_destroy (hb_font); + FT_Done_Face (ft_face); +} + +static void +test_has_data (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontNone.otf"); + g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + closeFont(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_ot_math_has_data (hb_face)); // MATH table available + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_constant (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert_cmpint(hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT), ==, 0); // MathConstants not available + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT)), ==, 100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT)), ==, 200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_MATH_LEADING)), ==, 300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_AXIS_HEIGHT)), ==, 400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT)), ==, 500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT)), ==, 600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN)), ==, 700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX)), ==, 800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN)), ==, 900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP)), ==, 1100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED)), ==, 1200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN)), ==, 1300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN)), ==, 2300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP)), ==, 2400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP)), ==, 2500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN)), ==, 2600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN)), ==, 2700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_GAP_MIN)), ==, 2800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN)), ==, 2900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP)), ==, 3000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN)), ==, 3100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN)), ==, 3200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN)), ==, 3300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP)), ==, 3400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP)), ==, 3500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN)), ==, 3600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN)), ==, 3700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN)), ==, 3800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN)), ==, 3900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER)), ==, 4700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP)), ==, 4800); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS)), ==, 4900); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER)), ==, 5000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP)), ==, 5100); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_italics_correction (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // MathItalicsCorrectionInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. + g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197); + g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150); + g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_top_accent_attachment (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. + g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318); + closeFont(); + + cleanupFreeType(); +} + +static void +test_is_glyph_extended_shape (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); // MathGlyphInfo empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "G", -1, &glyph)); + g_assert(!hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); + g_assert(hb_font_get_glyph_from_name (hb_font, "H", -1, &glyph)); + g_assert(hb_ot_math_is_glyph_extended_shape (hb_face, glyph)); + closeFont(); + + cleanupFreeType(); +} + +static void +test_get_glyph_kerning (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathGlyphInfo not available + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfo empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0), ==, 0); // MathKernInfoRecords empty + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 0), ==, 0); // MathKernInfoRecords empty + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); + + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + + closeFont(); + + cleanupFreeType(); +} + + +#if 0 +static void +test_get_math_italic_correction_for_glyph_assembly (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); + closeFont(); + + cleanupFreeType(); +} +#endif + +int +main (int argc, char **argv) +{ + hb_test_init (&argc, &argv); + + hb_test_add (test_has_data); + hb_test_add (test_get_constant); + hb_test_add (test_get_glyph_italics_correction); + hb_test_add (test_get_glyph_top_accent_attachment); + hb_test_add (test_is_glyph_extended_shape); + hb_test_add (test_get_glyph_kerning); + //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); + + return hb_test_run(); +} From cdc9eef7da934ae71578694f29665e439686c3bd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Sep 2016 22:18:41 +0200 Subject: [PATCH 0065/1326] [MATH] Enable tests for glyph-assembly italics-correction --- test/api/test-ot-math.c | 49 +++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 23c19eff3..4a7968129 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -314,55 +314,66 @@ test_get_glyph_kerning (void) } -#if 0 -static void -test_get_math_italic_correction_for_glyph_assembly (void) +static hb_position_t +get_glyph_assembly_italics_correction (hb_font_t *font, + hb_codepoint_t glyph, + hb_bool_t horizontal) +{ + hb_position_t corr; + unsigned int count = 0; + hb_ot_math_get_glyph_assembly (font, glyph, + horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB, + 0, &count, NULL, + &corr); + return corr; +} + +test_get_glyph_assembly_italics_correction (void) { hb_codepoint_t glyph; initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // MathVariants not available - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // MathVariants not available + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // MathVariants not available + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // MathVariants not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage absent closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // VertGlyphCoverage and HorizGlyphCoverage empty closeFont(); openFont("fonts/MathTestFontPartial3.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); // HorizGlyphConstruction and VertGlyphConstruction empty closeFont(); openFont("fonts/MathTestFontPartial4.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 124); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(hb_ot_layout_get_math_italic_correction_for_glyph_assembly (hb_font, glyph, FALSE), ==, 331); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331); closeFont(); cleanupFreeType(); } -#endif int main (int argc, char **argv) @@ -375,7 +386,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_top_accent_attachment); hb_test_add (test_is_glyph_extended_shape); hb_test_add (test_get_glyph_kerning); - //hb_test_add (test_get_math_italic_correction_for_glyph_assembly); + hb_test_add (test_get_glyph_assembly_italics_correction); return hb_test_run(); } From bc19f7fe20e89823dba07a46c3d48c7406b781b6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 10:58:08 +0200 Subject: [PATCH 0066/1326] [MATH] Add HB_OT_MATH_SCRIPT --- src/hb-ot-math.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index ad8bf14e5..814e40424 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -42,6 +42,9 @@ HB_BEGIN_DECLS #define HB_OT_TAG_MATH HB_TAG('M','A','T','H') +/* Use with hb_buffer_set_script() for math shaping. */ +#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') + /* Types */ typedef enum { From edcfa789bf92c18f5badad31c0ad04a6a77d7226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 11:02:08 +0200 Subject: [PATCH 0067/1326] test-ot-math: Use different scales for vertical and horizontal directions and add test for hb_ot_math_get_min_connector_overlap. (#327) --- test/api/test-ot-math.c | 79 +++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4a7968129..4bffcc049 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -63,8 +63,7 @@ openFont(const char* fontFile) } g_free(path); -#define fontSize 1000 - if ((ft_error = FT_Set_Char_Size (ft_face, fontSize, fontSize, 0, 0))) + if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); hb_face = hb_ft_face_create_cached(ft_face); @@ -118,7 +117,7 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX)), ==, 1400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN)), ==, 1500); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT)), ==, 1600); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 1700); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT)), ==, 3400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN)), ==, 1800); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN)), ==, 1900); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN)), ==, 2200); @@ -142,7 +141,7 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS)), ==, 4000); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN)), ==, 4100); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN)), ==, 4200); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 4300); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP)), ==, 8600); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP)), ==, 4400); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP)), ==, 4500); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS)), ==, 4600); @@ -154,8 +153,8 @@ test_get_constant (void) g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP)), ==, 5200); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS)), ==, 5300); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER)), ==, 5400); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 5500); - g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 5600); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE)), ==, 11000); + g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE)), ==, 11200); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 87); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN)), ==, 76); g_assert_cmpint((hb_ot_math_get_constant (hb_font, HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT)), ==, 65); @@ -189,11 +188,11 @@ test_get_glyph_italics_correction (void) g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 0); // Glyph without italic correction. g_assert(hb_font_get_glyph_from_name (hb_font, "A", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 197); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 394); g_assert(hb_font_get_glyph_from_name (hb_font, "B", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 150); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 300); g_assert(hb_font_get_glyph_from_name (hb_font, "C", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 452); + g_assert_cmpint(hb_ot_math_get_glyph_italics_correction (hb_font, glyph), ==, 904); closeFont(); cleanupFreeType(); @@ -207,28 +206,28 @@ test_get_glyph_top_accent_attachment (void) openFont("fonts/MathTestFontEmpty.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo not available + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo not available closeFont(); openFont("fonts/MathTestFontPartial1.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathGlyphInfo empty + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathGlyphInfo empty closeFont(); openFont("fonts/MathTestFontPartial2.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // MathTopAccentAttachment empty + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // MathTopAccentAttachment empty closeFont(); openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 500); // Glyph without top accent attachment. + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 1000); // Glyph without top accent attachment. g_assert(hb_font_get_glyph_from_name (hb_font, "D", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 374); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 748); g_assert(hb_font_get_glyph_from_name (hb_font, "E", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 346); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 692); g_assert(hb_font_get_glyph_from_name (hb_font, "F", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 318); + g_assert_cmpint(hb_ot_math_get_glyph_top_accent_attachment (hb_font, glyph), ==, 636); closeFont(); cleanupFreeType(); @@ -293,20 +292,20 @@ test_get_glyph_kerning (void) openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "I", -1, &glyph)); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 31); // lower than min heigth - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 31); // equal to min height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 52); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 52); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 73); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 73); - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 199); // equal to max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 220); // larger than max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 220); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 7), ==, 62); // lower than min heigth + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 14), ==, 62); // equal to min height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 20), ==, 104); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 23), ==, 104); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 31), ==, 146); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 32), ==, 146); + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 86), ==, 398); // equal to max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 91), ==, 440); // larger than max height + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 96), ==, 440); // larger than max height - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 94); // top right - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 55); // top left - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 22); // bottom right - g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 50); // bottom left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_RIGHT, 39), ==, 188); // top right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_TOP_LEFT, 39), ==, 110); // top left + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_RIGHT, 39), ==, 44); // bottom right + g_assert_cmpint(hb_ot_math_get_glyph_kerning (hb_font, glyph, HB_OT_MATH_KERN_BOTTOM_LEFT, 39), ==, 100); // bottom left closeFont(); @@ -365,11 +364,28 @@ test_get_glyph_assembly_italics_correction (void) openFont("fonts/MathTestFontFull.otf"); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 124); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 248); g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, TRUE), ==, 0); - g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 331); + g_assert_cmpint(get_glyph_assembly_italics_correction (hb_font, glyph, FALSE), ==, 662); + closeFont(); + + cleanupFreeType(); +} + +test_get_min_connector_overlap (void) +{ + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, FALSE), ==, 0); // MathVariants not available + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, TRUE), ==, 0); // MathVariants not available + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_LTR), ==, 108); + g_assert_cmpint(hb_ot_math_get_min_connector_overlap(hb_font, HB_DIRECTION_TTB), ==, 54); closeFont(); cleanupFreeType(); @@ -387,6 +403,7 @@ main (int argc, char **argv) hb_test_add (test_is_glyph_extended_shape); hb_test_add (test_get_glyph_kerning); hb_test_add (test_get_glyph_assembly_italics_correction); + hb_test_add (test_get_min_connector_overlap); return hb_test_run(); } From a5629a2ed9c2e69f2b4ebb74d85fbe0b5ba2be67 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 11:30:44 +0200 Subject: [PATCH 0068/1326] [MATH] Simplify test --- test/api/test-ot-math.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4bffcc049..668cc97ec 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -319,10 +319,9 @@ get_glyph_assembly_italics_correction (hb_font_t *font, hb_bool_t horizontal) { hb_position_t corr; - unsigned int count = 0; hb_ot_math_get_glyph_assembly (font, glyph, horizontal ? HB_DIRECTION_LTR : HB_DIRECTION_TTB, - 0, &count, NULL, + 0, NULL, NULL, &corr); return corr; } From f16bf6c2dacf5b9c82b2d1ffacc092cc396189a7 Mon Sep 17 00:00:00 2001 From: Phil Krylov Date: Tue, 27 Sep 2016 12:38:49 +0200 Subject: [PATCH 0069/1326] Allow building with graphite2 without pkg-config (#318) --- configure.ac | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/configure.ac b/configure.ac index ea6fc27cb..318c1efe4 100644 --- a/configure.ac +++ b/configure.ac @@ -307,6 +307,16 @@ GRAPHITE2_DEPS="graphite2" AC_SUBST(GRAPHITE2_DEPS) if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then PKG_CHECK_MODULES(GRAPHITE2, $GRAPHITE2_DEPS, have_graphite2=true, :) + if test "x$have_graphite2" != "xtrue"; then + # If pkg-config is not available, graphite2 can still be there + ac_save_CFLAGS="$CFLAGS" + ac_save_CPPFLAGS="$CPPFLAGS" + CFLAGS="$CFLAGS $GRAPHITE2_CFLAGS" + CPPFLAGS="$CPPFLAGS $GRAPHITE2_CFLAGS" + AC_CHECK_HEADER(graphite2/Segment.h, have_graphite2=true, :) + CPPFLAGS="$ac_save_CPPFLAGS" + CFLAGS="$ac_save_CFLAGS" + fi fi if test "x$with_graphite2" = "xyes" -a "x$have_graphite2" != "xtrue"; then AC_MSG_ERROR([graphite2 support requested but libgraphite2 not found]) From 485e4873fb7cacfa9d853272c2275bbc5826023e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 13:18:00 +0200 Subject: [PATCH 0070/1326] Add tests for hb_ot_math_get_glyph_variants (#328) --- test/api/test-ot-math.c | 126 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 668cc97ec..99993e063 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -326,6 +326,7 @@ get_glyph_assembly_italics_correction (hb_font_t *font, return corr; } +static void test_get_glyph_assembly_italics_correction (void) { hb_codepoint_t glyph; @@ -373,6 +374,7 @@ test_get_glyph_assembly_italics_correction (void) cleanupFreeType(); } +static void test_get_min_connector_overlap (void) { initFreeType(); @@ -390,6 +392,129 @@ test_get_min_connector_overlap (void) cleanupFreeType(); } +static void +test_get_glyph_variants (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL), ==, 3); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL), ==, 4); + g_assert_cmpint(hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL), ==, 0); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); + hb_math_glyph_variant_t variants[20]; + unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); + unsigned int count; + unsigned int offset = 0; + do { + count = variantsSize; + hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_RTL, + offset, + &count, + variants); + offset += count; + } while (count == variantsSize); + g_assert_cmpint(offset, ==, 3); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size2", -1, &glyph)); + g_assert_cmpint(variants[0].glyph, ==, glyph); + g_assert_cmpint(variants[0].advance, ==, 4302); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size3", -1, &glyph)); + g_assert_cmpint(variants[1].glyph, ==, glyph); + g_assert_cmpint(variants[1].advance, ==, 4802); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2190_size4", -1, &glyph)); + g_assert_cmpint(variants[2].glyph, ==, glyph); + g_assert_cmpint(variants[2].advance, ==, 5802); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowup", -1, &glyph)); + offset = 0; + do { + count = variantsSize; + hb_ot_math_get_glyph_variants (hb_font, + glyph, + HB_DIRECTION_BTT, + offset, + &count, + variants); + offset += count; + } while (count == variantsSize); + g_assert_cmpint(offset, ==, 4); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size2", -1, &glyph)); + g_assert_cmpint(variants[0].glyph, ==, glyph); + g_assert_cmpint(variants[0].advance, ==, 2251); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size3", -1, &glyph)); + g_assert_cmpint(variants[1].glyph, ==, glyph); + g_assert_cmpint(variants[1].advance, ==, 2501); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size4", -1, &glyph)); + g_assert_cmpint(variants[2].glyph, ==, glyph); + g_assert_cmpint(variants[2].advance, ==, 3001); + g_assert(hb_font_get_glyph_from_name (hb_font, "uni2191_size5", -1, &glyph)); + g_assert_cmpint(variants[3].glyph, ==, glyph); + g_assert_cmpint(variants[3].advance, ==, 3751); + + closeFont(); + + cleanupFreeType(); +} + int main (int argc, char **argv) { @@ -403,6 +528,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_kerning); hb_test_add (test_get_glyph_assembly_italics_correction); hb_test_add (test_get_min_connector_overlap); + hb_test_add (test_get_glyph_variants); return hb_test_run(); } From f73a87d9a8c76a181794b74b527ea268048f78e3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 13:50:54 +0200 Subject: [PATCH 0071/1326] 1.3.2 --- NEWS | 7 +++++++ configure.ac | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 52686870c..ae0926e63 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Overview of changes leading to 1.3.2 +Wednesday, September 27, 2016 +==================================== + +- Fix build of hb-coretext on older OS X versions. + + Overview of changes leading to 1.3.1 Wednesday, September 7, 2016 ==================================== diff --git a/configure.ac b/configure.ac index 318c1efe4..57e9e6db6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.3.1], + [1.3.2], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 8d622f1114d6a0eca1786b94c7fc1a0bcd87f74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 13:53:34 +0200 Subject: [PATCH 0072/1326] Add tests for get_mathvariant (#329) --- test/api/test-ot-math.c | 160 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 99993e063..4d6f67bcd 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -515,6 +515,165 @@ test_get_glyph_variants (void) cleanupFreeType(); } +static void +test_get_glyph_assembly (void) +{ + hb_codepoint_t glyph; + initFreeType(); + + openFont("fonts/MathTestFontEmpty.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial1.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial2.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial3.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontPartial4.otf"); + g_assert(hb_font_get_glyph_from_name (hb_font, "space", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_RTL, 0, NULL, NULL, NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, glyph, HB_DIRECTION_BTT, 0, NULL, NULL, NULL), ==, 0); + closeFont(); + + openFont("fonts/MathTestFontFull.otf"); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL, + NULL), ==, 0); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL, + NULL), ==, 3); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + 0, + NULL, + NULL, + NULL), ==, 5); + g_assert_cmpint(hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + 0, + NULL, + NULL, + NULL), ==, 0); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); + hb_math_glyph_part_t parts[20]; + unsigned partsSize = sizeof (parts) / sizeof (parts[0]); + unsigned int count; + unsigned int offset = 0; + do { + count = partsSize; + hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_RTL, + offset, + &count, + parts, + NULL); + offset += count; + } while (count == partsSize); + g_assert_cmpint(offset, ==, 3); + g_assert(hb_font_get_glyph_from_name (hb_font, "left", -1, &glyph)); + g_assert_cmpint(parts[0].glyph, ==, glyph); + g_assert_cmpint(parts[0].start_connector_length, ==, 800); + g_assert_cmpint(parts[0].end_connector_length, ==, 384); + g_assert_cmpint(parts[0].full_advance, ==, 2000); + g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "horizontal", -1, &glyph)); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].start_connector_length, ==, 524); + g_assert_cmpint(parts[1].end_connector_length, ==, 800); + g_assert_cmpint(parts[1].full_advance, ==, 2000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "right", -1, &glyph)); + g_assert_cmpint(parts[2].glyph, ==, glyph); + g_assert_cmpint(parts[2].start_connector_length, ==, 316); + g_assert_cmpint(parts[2].end_connector_length, ==, 454); + g_assert_cmpint(parts[2].full_advance, ==, 2000); + g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + + g_assert(hb_font_get_glyph_from_name (hb_font, "arrowdown", -1, &glyph)); + offset = 0; + do { + count = partsSize; + hb_ot_math_get_glyph_assembly (hb_font, + glyph, + HB_DIRECTION_BTT, + offset, + &count, + parts, + NULL); + offset += count; + } while (count == partsSize); + g_assert_cmpint(offset, ==, 5); + g_assert(hb_font_get_glyph_from_name (hb_font, "bottom", -1, &glyph)); + g_assert_cmpint(parts[0].glyph, ==, glyph); + g_assert_cmpint(parts[0].start_connector_length, ==, 365); + g_assert_cmpint(parts[0].end_connector_length, ==, 158); + g_assert_cmpint(parts[0].full_advance, ==, 1000); + g_assert(!(parts[0].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].glyph, ==, glyph); + g_assert_cmpint(parts[1].start_connector_length, ==, 227); + g_assert_cmpint(parts[1].end_connector_length, ==, 365); + g_assert_cmpint(parts[1].full_advance, ==, 1000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "center", -1, &glyph)); + g_assert_cmpint(parts[2].glyph, ==, glyph); + g_assert_cmpint(parts[2].start_connector_length, ==, 54); + g_assert_cmpint(parts[2].end_connector_length, ==, 158); + g_assert_cmpint(parts[2].full_advance, ==, 1000); + g_assert(!(parts[2].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + g_assert(hb_font_get_glyph_from_name (hb_font, "vertical", -1, &glyph)); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].glyph, ==, glyph); + g_assert_cmpint(parts[3].start_connector_length, ==, 400); + g_assert_cmpint(parts[3].end_connector_length, ==, 296); + g_assert_cmpint(parts[3].full_advance, ==, 1000); + g_assert(parts[1].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER); + g_assert(hb_font_get_glyph_from_name (hb_font, "top", -1, &glyph)); + g_assert_cmpint(parts[4].glyph, ==, glyph); + g_assert_cmpint(parts[4].start_connector_length, ==, 123); + g_assert_cmpint(parts[4].end_connector_length, ==, 192); + g_assert_cmpint(parts[4].full_advance, ==, 1000); + g_assert(!(parts[4].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)); + + closeFont(); + + cleanupFreeType(); +} + int main (int argc, char **argv) { @@ -529,6 +688,7 @@ main (int argc, char **argv) hb_test_add (test_get_glyph_assembly_italics_correction); hb_test_add (test_get_min_connector_overlap); hb_test_add (test_get_glyph_variants); + hb_test_add (test_get_glyph_assembly); return hb_test_run(); } From 0762b35474c47171e5661904e93851eb73a44e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 27 Sep 2016 15:28:35 +0200 Subject: [PATCH 0073/1326] Document API for MathVariants (#330) --- src/hb-ot-layout.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 588f5ab00..210af505d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1352,6 +1352,26 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); } +/** + * hb_ot_math_get_glyph_variants: + * + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first variant to retrieve + * @variants_count: maximum number of variants to retrieve after start_offset + * (IN) and actual number of variants retrieved (OUT) + * @variants: array of size at least @variants_count to store the result + * + * This function tries to retrieve the MathGlyphConstruction for the specified + * font, glyph and direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list + * of size variants as an array of hb_math_glyph_variant_t structs. + * + * Return value: the total number of size variants available or 0 + * + * Since: 1.4 + **/ unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, hb_codepoint_t glyph, @@ -1367,6 +1387,21 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, variants); } +/** + * hb_ot_math_get_min_connector_overlap: + * + * @font: #hb_font_t from which to retrieve the value + * @direction: direction of the stretching + * + * This function tries to retrieve the MathVariants table for the specified + * font and returns the minimum overlap of connecting glyphs to draw a glyph + * assembly in the specified direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. + * + * Return value: requested min connector overlap or 0 + * + * Since: 1.4 + **/ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, hb_direction_t direction) @@ -1375,6 +1410,27 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, return math.get_math_variants().get_min_connector_overlap (direction, font); } +/** + * hb_ot_math_get_glyph_assembly: + * + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first glyph part to retrieve + * @parts_count: maximum number of glyph parts to retrieve after start_offset + * (IN) and actual number of parts retrieved (OUT) + * @parts: array of size at least @parts_count to store the result + * @italics_correction: italic correction of the glyph assembly + * + * This function tries to retrieve the GlyphAssembly for the specified font, + * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL + * is considered. It provides the information necessary to draw the glyph + * assembly as an array of #hb_math_glyph_part_t. + * + * Return value: the total number of parts in the glyph assembly + * + * Since: 1.4 + **/ unsigned int hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_codepoint_t glyph, From db5ebcf10f8595d1f4a9df27befd6cb5e76ca94d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:42:25 +0200 Subject: [PATCH 0074/1326] Update docs --- docs/harfbuzz-docs.xml | 9 +++++++++ docs/harfbuzz-sections.txt | 30 ++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml index 2c43c4687..ea99732ca 100644 --- a/docs/harfbuzz-docs.xml +++ b/docs/harfbuzz-docs.xml @@ -80,6 +80,7 @@ + @@ -175,6 +176,14 @@ Index of new symbols in 1.1.3 + + Index of new symbols in 1.2.3 + + + + Index of new symbols in 1.4.0 + + Index of deprecated API diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index e0dc23d9c..d94cf703e 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -144,6 +144,8 @@ uint8_t HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_SCRIPT_CANADIAN_ABORIGINAL +hb_font_funcs_set_glyph_func +hb_font_get_glyph_func_t

    @@ -193,7 +195,6 @@ hb_font_funcs_reference hb_font_funcs_set_glyph_contour_point_func hb_font_funcs_set_glyph_extents_func hb_font_funcs_set_glyph_from_name_func -hb_font_funcs_set_glyph_func hb_font_funcs_set_glyph_h_advance_func hb_font_funcs_set_glyph_h_kerning_func hb_font_funcs_set_glyph_h_origin_func @@ -201,7 +202,9 @@ hb_font_funcs_set_glyph_name_func hb_font_funcs_set_glyph_v_advance_func hb_font_funcs_set_glyph_v_kerning_func hb_font_funcs_set_glyph_v_origin_func +hb_font_funcs_set_nominal_glyph_func hb_font_funcs_set_user_data +hb_font_funcs_set_variation_glyph_func hb_font_funcs_t hb_font_get_empty hb_font_get_face @@ -216,7 +219,6 @@ hb_font_get_glyph_extents_for_origin hb_font_get_glyph_extents_func_t hb_font_get_glyph_from_name hb_font_get_glyph_from_name_func_t -hb_font_get_glyph_func_t hb_font_get_glyph_h_advance hb_font_get_glyph_h_advance_func_t hb_font_get_glyph_h_kerning @@ -235,10 +237,14 @@ hb_font_get_glyph_v_kerning hb_font_get_glyph_v_kerning_func_t hb_font_get_glyph_v_origin hb_font_get_glyph_v_origin_func_t +hb_font_get_nominal_glyph +hb_font_get_nominal_glyph_func_t hb_font_get_parent hb_font_get_ppem hb_font_get_scale hb_font_get_user_data +hb_font_get_variation_glyph +hb_font_get_variation_glyph_func_t hb_font_glyph_from_string hb_font_glyph_to_string hb_font_is_immutable @@ -416,6 +422,26 @@ Xhb_ot_layout_lookup_position Xhb_ot_layout_lookup_substitute
    +
    +hb-ot-math +HB_OT_TAG_MATH +HB_OT_MATH_SCRIPT +hb_math_glyph_part_flags_t +hb_math_glyph_part_t +hb_math_glyph_variant_t +hb_ot_math_constant_t +hb_ot_math_get_constant +hb_ot_math_get_glyph_assembly +hb_ot_math_get_glyph_italics_correction +hb_ot_math_get_glyph_kerning +hb_ot_math_get_glyph_top_accent_attachment +hb_ot_math_get_glyph_variants +hb_ot_math_get_min_connector_overlap +hb_ot_math_has_data +hb_ot_math_is_glyph_extended_shape +hb_ot_math_kern_t +
    +
    hb-ot-tag HB_OT_TAG_DEFAULT_LANGUAGE From 46cc4a3a2a529c80677babe38ca1542f9c773ac0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:44:22 +0200 Subject: [PATCH 0075/1326] [MATH] Rename hb_math_*_t types to hb_ot_math_*_t With this, I believe MATH table API is not ready to be merged. --- docs/harfbuzz-sections.txt | 6 +++--- src/hb-ot-layout-math-table.hh | 12 ++++++------ src/hb-ot-layout.cc | 8 ++++---- src/hb-ot-math.h | 16 ++++++++-------- test/api/test-ot-math.c | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index d94cf703e..75d749293 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -426,10 +426,10 @@ Xhb_ot_layout_lookup_substitute hb-ot-math HB_OT_TAG_MATH HB_OT_MATH_SCRIPT -hb_math_glyph_part_flags_t -hb_math_glyph_part_t -hb_math_glyph_variant_t hb_ot_math_constant_t +hb_ot_math_glyph_part_flags_t +hb_ot_math_glyph_part_t +hb_ot_math_glyph_variant_t hb_ot_math_get_constant hb_ot_math_get_glyph_assembly hb_ot_math_get_glyph_italics_correction diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index efffd2b53..b52b1215d 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -453,7 +453,7 @@ struct MathGlyphPartRecord return_trace (c->check_struct (this)); } - inline void extract (hb_math_glyph_part_t &out, + inline void extract (hb_ot_math_glyph_part_t &out, int scale, hb_font_t *font) const { @@ -466,7 +466,7 @@ struct MathGlyphPartRecord ASSERT_STATIC ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == (unsigned int) PartFlags::Extender); - out.flags = (hb_math_glyph_part_flags_t) + out.flags = (hb_ot_math_glyph_part_flags_t) (unsigned int) (partFlags & PartFlags::Defined); } @@ -504,7 +504,7 @@ struct MathGlyphAssembly hb_font_t *font, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts /* OUT */, + hb_ot_math_glyph_part_t *parts /* OUT */, hb_position_t *italics_correction /* OUT */) const { if (parts_count) @@ -552,7 +552,7 @@ struct MathGlyphConstruction hb_font_t *font, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) const + hb_ot_math_glyph_variant_t *variants /* OUT */) const { if (variants_count) { @@ -613,7 +613,7 @@ struct MathVariants hb_font_t *font, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) const + hb_ot_math_glyph_variant_t *variants /* OUT */) const { return get_glyph_construction (glyph, direction, font) .get_variants (direction, font, start_offset, variants_count, variants); } @@ -622,7 +622,7 @@ struct MathVariants hb_font_t *font, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts /* OUT */, + hb_ot_math_glyph_part_t *parts /* OUT */, hb_position_t *italics_correction /* OUT */) const { return get_glyph_construction (glyph, direction, font) .get_assembly () diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 210af505d..49c75b0be 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1366,7 +1366,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, * This function tries to retrieve the MathGlyphConstruction for the specified * font, glyph and direction. Note that only the value of * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list - * of size variants as an array of hb_math_glyph_variant_t structs. + * of size variants as an array of hb_ot_math_glyph_variant_t structs. * * Return value: the total number of size variants available or 0 * @@ -1378,7 +1378,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */) + hb_ot_math_glyph_variant_t *variants /* OUT */) { const OT::MATH &math = _get_math (font->face); return math.get_math_variants().get_glyph_variants (glyph, direction, font, @@ -1425,7 +1425,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, * This function tries to retrieve the GlyphAssembly for the specified font, * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL * is considered. It provides the information necessary to draw the glyph - * assembly as an array of #hb_math_glyph_part_t. + * assembly as an array of #hb_ot_math_glyph_part_t. * * Return value: the total number of parts in the glyph assembly * @@ -1437,7 +1437,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */) { const OT::MATH &math = _get_math (font->face); diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 814e40424..e186fa989 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -113,22 +113,22 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; -typedef struct hb_math_glyph_variant_t { +typedef struct hb_ot_math_glyph_variant_t { hb_codepoint_t glyph; hb_position_t advance; -} hb_math_glyph_variant_t; +} hb_ot_math_glyph_variant_t; typedef enum { /*< flags >*/ HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ -} hb_math_glyph_part_flags_t; +} hb_ot_math_glyph_part_flags_t; -typedef struct hb_math_glyph_part_t { +typedef struct hb_ot_math_glyph_part_t { hb_codepoint_t glyph; hb_position_t start_connector_length; hb_position_t end_connector_length; hb_position_t full_advance; - hb_math_glyph_part_flags_t flags; -} hb_math_glyph_part_t; + hb_ot_math_glyph_part_flags_t flags; +} hb_ot_math_glyph_part_t; /* Methods */ @@ -163,7 +163,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *variants_count, /* IN/OUT */ - hb_math_glyph_variant_t *variants /* OUT */); + hb_ot_math_glyph_variant_t *variants /* OUT */); HB_EXTERN hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, @@ -175,7 +175,7 @@ hb_ot_math_get_glyph_assembly (hb_font_t *font, hb_direction_t direction, unsigned int start_offset, unsigned int *parts_count, /* IN/OUT */ - hb_math_glyph_part_t *parts, /* OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ hb_position_t *italics_correction /* OUT */); diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 4d6f67bcd..5f4ccb7fc 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -459,7 +459,7 @@ test_get_glyph_variants (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - hb_math_glyph_variant_t variants[20]; + hb_ot_math_glyph_variant_t variants[20]; unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); unsigned int count; unsigned int offset = 0; @@ -586,7 +586,7 @@ test_get_glyph_assembly (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); - hb_math_glyph_part_t parts[20]; + hb_ot_math_glyph_part_t parts[20]; unsigned partsSize = sizeof (parts) / sizeof (parts[0]); unsigned int count; unsigned int offset = 0; From c3e21a6620c35500afa350d11620f69802920df3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 16:51:38 +0200 Subject: [PATCH 0076/1326] [MATH] Fix more docs --- src/hb-ot-layout.cc | 18 +++++++++--------- src/hb-ot-math.h | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 49c75b0be..6c8a9c498 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1238,7 +1238,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * * Return value: #TRUE if face has a MATH table and #FALSE otherwise * - * Since: 1.4 + * Since: 1.4.0 **/ hb_bool_t hb_ot_math_has_data (hb_face_t *face) @@ -1260,7 +1260,7 @@ hb_ot_math_has_data (hb_face_t *face) * * Return value: the requested constant or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_constant (hb_font_t *font, @@ -1278,7 +1278,7 @@ hb_ot_math_get_constant (hb_font_t *font, * * Return value: the italics correction of the glyph or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_italics_correction (hb_font_t *font, @@ -1296,7 +1296,7 @@ hb_ot_math_get_glyph_italics_correction (hb_font_t *font, * * Return value: the top accent attachment of the glyph or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, @@ -1314,7 +1314,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise * - * Since: 1.4 + * Since: 1.4.0 **/ hb_bool_t hb_ot_math_is_glyph_extended_shape (hb_face_t *face, @@ -1340,7 +1340,7 @@ hb_ot_math_is_glyph_extended_shape (hb_face_t *face, * * Return value: requested kerning or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_glyph_kerning (hb_font_t *font, @@ -1370,7 +1370,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, * * Return value: the total number of size variants available or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, @@ -1400,7 +1400,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, * * Return value: requested min connector overlap or 0 * - * Since: 1.4 + * Since: 1.4.0 **/ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, @@ -1429,7 +1429,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, * * Return value: the total number of parts in the glyph assembly * - * Since: 1.4 + * Since: 1.4.0 **/ unsigned int hb_ot_math_get_glyph_assembly (hb_font_t *font, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index e186fa989..0fc251b55 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -47,6 +47,11 @@ HB_BEGIN_DECLS /* Types */ +/** + * hb_ot_math_constant_t: + * + * Since: 1.4.0 + */ typedef enum { HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1, @@ -106,6 +111,11 @@ typedef enum { HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55 } hb_ot_math_constant_t; +/** + * hb_ot_math_kern_t: + * + * Since: 1.4.0 + */ typedef enum { HB_OT_MATH_KERN_TOP_RIGHT = 0, HB_OT_MATH_KERN_TOP_LEFT = 1, @@ -113,15 +123,30 @@ typedef enum { HB_OT_MATH_KERN_BOTTOM_LEFT = 3 } hb_ot_math_kern_t; +/** + * hb_ot_math_glyph_variant_t: + * + * Since: 1.4.0 + */ typedef struct hb_ot_math_glyph_variant_t { hb_codepoint_t glyph; hb_position_t advance; } hb_ot_math_glyph_variant_t; +/** + * hb_ot_math_glyph_part_flags_t: + * + * Since: 1.4.0 + */ typedef enum { /*< flags >*/ HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ } hb_ot_math_glyph_part_flags_t; +/** + * hb_ot_math_glyph_part_t: + * + * Since: 1.4.0 + */ typedef struct hb_ot_math_glyph_part_t { hb_codepoint_t glyph; hb_position_t start_connector_length; From fd7a245d3525905ffbce57472b52900fcb0e330b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 27 Sep 2016 17:56:35 +0200 Subject: [PATCH 0077/1326] Require glib >= 2.38.0 for G_TEST_DIST --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 57e9e6db6..4c3d402d6 100644 --- a/configure.ac +++ b/configure.ac @@ -145,7 +145,7 @@ AC_ARG_WITH(glib, [Use glib @<:@default=auto@:>@])],, [with_glib=auto]) have_glib=false -GLIB_DEPS="glib-2.0 >= 2.16" +GLIB_DEPS="glib-2.0 >= 2.38" AC_SUBST(GLIB_DEPS) if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :) From 7adbc5dd62ca03a65d1886e0f32e7026964dc5e5 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 30 Sep 2016 04:01:24 -0700 Subject: [PATCH 0078/1326] Fix building math docs (#335) --- src/hb-ot-layout.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6c8a9c498..0826607d9 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1229,7 +1229,6 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, /** * hb_ot_math_has_data: - * * @face: #hb_face_t to test * * This function allows to verify the presence of an OpenType MATH table on the @@ -1248,7 +1247,6 @@ hb_ot_math_has_data (hb_face_t *face) /** * hb_ot_math_get_constant: - * * @font: #hb_font_t from which to retrieve the value * @constant: #hb_ot_math_constant_t the constant to retrieve * @@ -1272,7 +1270,6 @@ hb_ot_math_get_constant (hb_font_t *font, /** * hb_ot_math_get_glyph_italics_correction: - * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value * @@ -1290,7 +1287,6 @@ hb_ot_math_get_glyph_italics_correction (hb_font_t *font, /** * hb_ot_math_get_glyph_top_accent_attachment: - * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value * @@ -1308,7 +1304,6 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, /** * hb_ot_math_is_glyph_extended_shape: - * * @font: a #hb_font_t to test * @glyph: a glyph index to test * @@ -1326,7 +1321,6 @@ hb_ot_math_is_glyph_extended_shape (hb_face_t *face, /** * hb_ot_math_get_glyph_kerning: - * * @font: #hb_font_t from which to retrieve the value * @glyph: glyph index from which to retrieve the value * @kern: the #hb_ot_math_kern_t from which to retrieve the value @@ -1354,7 +1348,6 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, /** * hb_ot_math_get_glyph_variants: - * * @font: #hb_font_t from which to retrieve the values * @glyph: index of the glyph to stretch * @direction: direction of the stretching @@ -1389,7 +1382,6 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, /** * hb_ot_math_get_min_connector_overlap: - * * @font: #hb_font_t from which to retrieve the value * @direction: direction of the stretching * @@ -1412,7 +1404,6 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, /** * hb_ot_math_get_glyph_assembly: - * * @font: #hb_font_t from which to retrieve the values * @glyph: index of the glyph to stretch * @direction: direction of the stretching From d1c62370a0c2bdb365a1468dc8d782b9a7245946 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Sep 2016 19:11:22 +0200 Subject: [PATCH 0079/1326] Aim math API for 1.3.3 instead of 1.4.0 --- docs/harfbuzz-docs.xml | 6 +++--- docs/harfbuzz-sections.txt | 12 ++++++------ src/hb-ot-layout.cc | 18 +++++++++--------- src/hb-ot-math.h | 10 +++++----- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml index ea99732ca..7a42d2378 100644 --- a/docs/harfbuzz-docs.xml +++ b/docs/harfbuzz-docs.xml @@ -180,9 +180,9 @@ Index of new symbols in 1.2.3 - - Index of new symbols in 1.4.0 - + + Index of new symbols in 1.3.3 + Index of deprecated API diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 75d749293..270c87c44 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -427,19 +427,19 @@ Xhb_ot_layout_lookup_substitute HB_OT_TAG_MATH HB_OT_MATH_SCRIPT hb_ot_math_constant_t +hb_ot_math_kern_t +hb_ot_math_glyph_variant_t hb_ot_math_glyph_part_flags_t hb_ot_math_glyph_part_t -hb_ot_math_glyph_variant_t +hb_ot_math_has_data hb_ot_math_get_constant -hb_ot_math_get_glyph_assembly hb_ot_math_get_glyph_italics_correction -hb_ot_math_get_glyph_kerning hb_ot_math_get_glyph_top_accent_attachment +hb_ot_math_get_glyph_kerning +hb_ot_math_is_glyph_extended_shape hb_ot_math_get_glyph_variants hb_ot_math_get_min_connector_overlap -hb_ot_math_has_data -hb_ot_math_is_glyph_extended_shape -hb_ot_math_kern_t +hb_ot_math_get_glyph_assembly
    diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0826607d9..0501181a3 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1237,7 +1237,7 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, * * Return value: #TRUE if face has a MATH table and #FALSE otherwise * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_bool_t hb_ot_math_has_data (hb_face_t *face) @@ -1258,7 +1258,7 @@ hb_ot_math_has_data (hb_face_t *face) * * Return value: the requested constant or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_position_t hb_ot_math_get_constant (hb_font_t *font, @@ -1275,7 +1275,7 @@ hb_ot_math_get_constant (hb_font_t *font, * * Return value: the italics correction of the glyph or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_position_t hb_ot_math_get_glyph_italics_correction (hb_font_t *font, @@ -1292,7 +1292,7 @@ hb_ot_math_get_glyph_italics_correction (hb_font_t *font, * * Return value: the top accent attachment of the glyph or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_position_t hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, @@ -1309,7 +1309,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_bool_t hb_ot_math_is_glyph_extended_shape (hb_face_t *face, @@ -1334,7 +1334,7 @@ hb_ot_math_is_glyph_extended_shape (hb_face_t *face, * * Return value: requested kerning or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_position_t hb_ot_math_get_glyph_kerning (hb_font_t *font, @@ -1363,7 +1363,7 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font, * * Return value: the total number of size variants available or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ unsigned int hb_ot_math_get_glyph_variants (hb_font_t *font, @@ -1392,7 +1392,7 @@ hb_ot_math_get_glyph_variants (hb_font_t *font, * * Return value: requested min connector overlap or 0 * - * Since: 1.4.0 + * Since: 1.3.3 **/ hb_position_t hb_ot_math_get_min_connector_overlap (hb_font_t *font, @@ -1420,7 +1420,7 @@ hb_ot_math_get_min_connector_overlap (hb_font_t *font, * * Return value: the total number of parts in the glyph assembly * - * Since: 1.4.0 + * Since: 1.3.3 **/ unsigned int hb_ot_math_get_glyph_assembly (hb_font_t *font, diff --git a/src/hb-ot-math.h b/src/hb-ot-math.h index 0fc251b55..521a5ca03 100644 --- a/src/hb-ot-math.h +++ b/src/hb-ot-math.h @@ -50,7 +50,7 @@ HB_BEGIN_DECLS /** * hb_ot_math_constant_t: * - * Since: 1.4.0 + * Since: 1.3.3 */ typedef enum { HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0, @@ -114,7 +114,7 @@ typedef enum { /** * hb_ot_math_kern_t: * - * Since: 1.4.0 + * Since: 1.3.3 */ typedef enum { HB_OT_MATH_KERN_TOP_RIGHT = 0, @@ -126,7 +126,7 @@ typedef enum { /** * hb_ot_math_glyph_variant_t: * - * Since: 1.4.0 + * Since: 1.3.3 */ typedef struct hb_ot_math_glyph_variant_t { hb_codepoint_t glyph; @@ -136,7 +136,7 @@ typedef struct hb_ot_math_glyph_variant_t { /** * hb_ot_math_glyph_part_flags_t: * - * Since: 1.4.0 + * Since: 1.3.3 */ typedef enum { /*< flags >*/ HB_MATH_GLYPH_PART_FLAG_EXTENDER = 0x00000001u /* Extender glyph */ @@ -145,7 +145,7 @@ typedef enum { /*< flags >*/ /** * hb_ot_math_glyph_part_t: * - * Since: 1.4.0 + * Since: 1.3.3 */ typedef struct hb_ot_math_glyph_part_t { hb_codepoint_t glyph; From 34fc4a2cfa61089b7ec2d9510d99cdc4c13bceb4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Sep 2016 19:17:27 +0200 Subject: [PATCH 0080/1326] Fix dist --- test/api/Makefile.am | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/api/Makefile.am b/test/api/Makefile.am index 58f49146a..d514a6f82 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -54,6 +54,16 @@ TEST_PROGS += \ $(NULL) test_ot_math_LDADD = $(LDADD) $(FREETYPE_LIBS) test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) +EXTRA_DIST += \ + fonts/MathTestFontEmpty.otf \ + fonts/MathTestFontFull.otf \ + fonts/MathTestFontFull.ttx \ + fonts/MathTestFontNone.otf \ + fonts/MathTestFontPartial1.otf \ + fonts/MathTestFontPartial2.otf \ + fonts/MathTestFontPartial3.otf \ + fonts/MathTestFontPartial4.otf \ + $(NULL) endif # HAVE_FREETYPE endif # HAVE_OT From 7201fdd0a8e26d49b13e289b53de375d5b1c9fcb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 4 Oct 2016 14:53:17 -0700 Subject: [PATCH 0081/1326] LFS (large file system?) support in hb-*shap*, hb-view Fixes https://github.com/behdad/harfbuzz/issues/336 --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 4c3d402d6..235afe761 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,8 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/harfbuzz.pc.in]) AC_CONFIG_HEADERS([config.h]) +AC_USE_SYSTEM_EXTENSIONS + AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability]) AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12) AM_SILENT_RULES([yes]) @@ -22,6 +24,7 @@ LT_INIT([disable-static]) AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CXX +AC_SYS_LARGEFILE PKG_PROG_PKG_CONFIG([0.20]) AM_MISSING_PROG([RAGEL], [ragel]) AM_MISSING_PROG([GIT], [git]) From bef240b36ee9086b0d92e351e4c5118c0bbb5df6 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Mon, 10 Oct 2016 17:27:52 +0330 Subject: [PATCH 0082/1326] [ci] Whitelist more symbols and unbreak mac CI Thanks to @khaledhosny, actually this is his work :) --- src/check-symbols.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/check-symbols.sh b/src/check-symbols.sh index b2bf43fce..ba09ba1cc 100755 --- a/src/check-symbols.sh +++ b/src/check-symbols.sh @@ -19,8 +19,8 @@ tested=false for suffix in so dylib; do so=.libs/libharfbuzz.$suffix if ! test -f "$so"; then continue; fi - - EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| llvm_' | cut -d' ' -f3`" + + EXPORTED_SYMBOLS="`nm "$so" | grep ' [BCDGINRSTVW] ' | grep -v ' _fini\>\| _init\>\| _fdata\>\| _ftext\>\| _fbss\>\| __bss_start\>\| __bss_start__\>\| __bss_end__\>\| _edata\>\| _end\>\| _bss_end__\>\| __end__\>\| __gcov_flush\>\| ___gcov_flush\>\| llvm_\| _llvm_' | cut -d' ' -f3`" prefix=`basename "$so" | sed 's/libharfbuzz/hb/; s/-/_/g; s/[.].*//'` From 331c46c79b4d18cb4948be12c78ebb71a143e7ac Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 11 Oct 2016 13:45:22 -0700 Subject: [PATCH 0083/1326] Fix configure on iOS Fixes https://github.com/behdad/harfbuzz/issues/342 --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 235afe761..14c86b7c5 100644 --- a/configure.ac +++ b/configure.ac @@ -414,7 +414,8 @@ if test "x$with_coretext" = "xyes" -o "x$with_coretext" = "xauto"; then else # On iOS CoreText and CoreGraphics are stand-alone frameworks if test "x$have_coretext" != "xtrue"; then - AC_CHECK_TYPE(CTFontRef, have_coretext=true,, [#include ]) + # Check for a different symbol to avoid getting cached result. + AC_CHECK_TYPE(CTRunRef, have_coretext=true,, [#include ]) fi if $have_coretext; then From d8e2eb9ee0f47af7e90056d8db5949d10a88786a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sun, 9 Oct 2016 09:06:05 +0330 Subject: [PATCH 0084/1326] Make Uniscribe optional on nmake win32 builds Most of harfbuzz clients don't need Uniscribe and DirectWrite support at all as harfbuzz is a replacement for Uniscribe so Chromium and Firefox are using harfbuzz without them on Windows. This removal also helps win32 nmake clients to have reduced binary size and libs count. --- appveyor.yml | 2 +- win32/README.txt | 13 +++++++------ win32/config-msvc.mak | 18 +++++++++++++----- win32/config.h.win32.in | 2 +- win32/info-msvc.mak | 11 +++++++++-- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4677a2774..cc16e5e78 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -31,7 +31,7 @@ build_script: - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32' - - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% DIRECTWRITE=1' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"' diff --git a/win32/README.txt b/win32/README.txt index e2ead01d0..07e211c0a 100644 --- a/win32/README.txt +++ b/win32/README.txt @@ -7,11 +7,10 @@ Makefiles. The following are instructions for performing such a build, as there is a number of build configurations supported for the build. Note that for all build configurations, the OpenType and Simple TrueType layout (fallback) -backends are enabled, as well as the Uniscribe platform shaper, and this -is the base configuration that is built if no options (see below) are -specified. A 'clean' target is provided-it is recommended that one cleans -the build and redo the build if any configuration option changed. An -'install' target is also provided to copy the built items in their appropriate +backends are enabled, and this is the base configuration that is built if no +options (see below) are specified. A 'clean' target is provided-it is recommended +that one cleans the build and redo the build if any configuration option changed. +An 'install' target is also provided to copy the built items in their appropriate locations under $(PREFIX), which is described below. Invoke the build by issuing the command: @@ -68,7 +67,9 @@ ICU: Enables the build HarfBuzz-ICU, which is now the recommended layout engine for ICU (International Components for Unicode), which deprecated ICU LE. Requires the ICU libraries. -DIRECTWRITE: Enable (experimental) DirectWrite platform shaper support, +UNISCRIBE: Enable Uniscribe platform shaper support. + +DIRECTWRITE: Enable DirectWrite platform shaper support, requires a rather recent Windows SDK, and at least Windows Vista/ Server 2008 with SP2 and platform update. diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak index e0c6468e3..88ae07168 100644 --- a/win32/config-msvc.mak +++ b/win32/config-msvc.mak @@ -20,6 +20,9 @@ CAIRO_LIB = cairo.lib # Graphite2 is needed for building SIL Graphite2 support GRAPHITE2_LIB = graphite2.lib +# Uniscribe is needed for Uniscribe shaping support +UNISCRIBE_LIB = usp10.lib gdi32.lib rpcrt4.lib user32.lib + # Directwrite is needed for DirectWrite shaping support DIRECTWRITE_LIB = dwrite.lib @@ -31,17 +34,15 @@ HB_UCDN_CFLAGS = /I..\src\hb-ucdn HB_SOURCES = \ $(HB_BASE_sources) \ $(HB_FALLBACK_sources) \ - $(HB_OT_sources) \ - $(HB_UNISCRIBE_sources) \ + $(HB_OT_sources) HB_HEADERS = \ $(HB_BASE_headers) \ $(HB_NODIST_headers) \ - $(HB_OT_headers) \ - $(HB_UNISCRIBE_headers) + $(HB_OT_headers) # Minimal set of (system) libraries needed for the HarfBuzz DLL -HB_DEP_LIBS = usp10.lib gdi32.lib rpcrt4.lib user32.lib +HB_DEP_LIBS = # We build the HarfBuzz DLL/LIB at least HB_LIBS = $(CFG)\$(PLAT)\harfbuzz.lib @@ -188,6 +189,13 @@ HB_CFLAGS = \ HB_SOURCES = $(HB_SOURCES) $(LIBHB_UCDN_sources) $(HB_UCDN_sources) !endif +!if "$(UNISCRIBE)" == "1" +HB_CFLAGS = $(HB_CFLAGS) /DHAVE_UNISCRIBE +HB_SOURCES = $(HB_SOURCES) $(HB_UNISCRIBE_sources) +HB_HEADERS = $(HB_HEADERS) $(HB_UNISCRIBE_headers) +HB_DEP_LIBS = $(HB_DEP_LIBS) $(UNISCRIBE_LIB) +!endif + !if "$(DIRECTWRITE)" == "1" HB_CFLAGS = $(HB_CFLAGS) /DHAVE_DIRECTWRITE HB_SOURCES = $(HB_SOURCES) $(HB_DIRECTWRITE_sources) diff --git a/win32/config.h.win32.in b/win32/config.h.win32.in index 73ad205d5..d45cefb5e 100644 --- a/win32/config.h.win32.in +++ b/win32/config.h.win32.in @@ -115,7 +115,7 @@ #define HAVE_UCDN 1 /* Have Uniscribe library */ -#define HAVE_UNISCRIBE 1 +/* #undef HAVE_UNISCRIBE */ /* Define to 1 if you have the header file. */ #ifndef _MSC_VER diff --git a/win32/info-msvc.mak b/win32/info-msvc.mak index bc85dc9c9..bbe631bd0 100644 --- a/win32/info-msvc.mak +++ b/win32/info-msvc.mak @@ -1,6 +1,6 @@ # NMake Makefile portion for displaying config info -INC_FEATURES = Uniscribe Fallback OT +INC_FEATURES = Fallback OT BUILT_TOOLS = BUILT_LIBRARIES = HarfBuzz @@ -23,6 +23,10 @@ INC_FEATURES = $(INC_FEATURES) FreeType INC_FEATURES = $(INC_FEATURES) Graphite2 !endif +!if "$(UNISCRIBE)" == "1" +INC_FEATURES = $(INC_FEATURES) Uniscribe +!endif + !if "$(DIRECTWRITE)" == "1" INC_FEATURES = $(INC_FEATURES) DirectWrite !endif @@ -77,9 +81,12 @@ help: @echo. @echo OPTION: Optional, may be any of the following, use OPTION=1 to enable; @echo multiple OPTION's may be used. If no OPTION is specified, a default - @echo HarfBuzz DLL is built with OpenType, fallback and Uniscribe support + @echo HarfBuzz DLL is built with OpenType and fallback support @echo with a bundled Unicode implementation (UCDN). @echo ====== + @echo UNISCRIBE: + @echo Enable Uniscribe support. + @echo. @echo DIRECTWRITE: @echo Enable DirectWrite support, requires a recent enough Windows SDK. @echo. From 4631d84c2bb51395efe3156f9c9f1a6b0e277947 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 18 Oct 2016 14:30:00 +0330 Subject: [PATCH 0085/1326] Merge back @vlj's local patches of vcpkg --- win32/config-msvc.mak | 7 +++++++ win32/detectenv-msvc.mak | 3 +++ 2 files changed, 10 insertions(+) diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak index 88ae07168..d8b851d1e 100644 --- a/win32/config-msvc.mak +++ b/win32/config-msvc.mak @@ -12,7 +12,11 @@ HB_GLIB_LIBS = glib-2.0.lib HB_GOBJECT_DEP_LIBS = gobject-2.0.lib $(HB_GLIB_LIBS) # Freetype is needed for building FreeType support and hb-view +!if "$(CFG)" == "debug" +FREETYPE_LIB = freetyped.lib +!else FREETYPE_LIB = freetype.lib +!endif # Cairo is needed for building hb-view CAIRO_LIB = cairo.lib @@ -125,6 +129,9 @@ HB_DEFINES = $(HB_DEFINES) /DHAVE_CAIRO=1 # Enable freetype if desired !if "$(FREETYPE)" == "1" +!if "$(FREETYPE_DIR)" != "" +HB_CFLAGS = $(HB_CFLAGS) /I$(FREETYPE_DIR) +!endif HB_DEFINES = $(HB_DEFINES) /DHAVE_FREETYPE=1 HB_SOURCES = $(HB_SOURCES) $(HB_FT_sources) HB_HEADERS = $(HB_HEADERS) $(HB_FT_headers) diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak index 83d87862c..41f4bd097 100644 --- a/win32/detectenv-msvc.mak +++ b/win32/detectenv-msvc.mak @@ -130,6 +130,9 @@ LDFLAGS_ARCH = /machine:x86 CFLAGS = $(CFLAGS_ADD) /W3 /Zi /I.. /I..\src /I. /I$(PREFIX)\include LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib /DEBUG +!if "$(ADDITIONAL_LIB_DIR)" != "" +LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(ADDITIONAL_LIB_DIR) +!endif !if "$(CFG)" == "debug" LDFLAGS = $(LDFLAGS_BASE) From 755a0c20798e3c3e6bb933a28e38f9667fccdadc Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 21 Oct 2016 11:48:58 +0330 Subject: [PATCH 0086/1326] [ci] Enable freetype on msvc using vcpkg --- appveyor.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index cc16e5e78..06530007b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,15 +4,19 @@ environment: matrix: - compiler: msvc ARCH: amd64 + VCPKG_ARCH: x64-windows CFG: release - compiler: msvc ARCH: x86 + VCPKG_ARCH: x86-windows CFG: release - compiler: msvc ARCH: amd64 + VCPKG_ARCH: x64-windows CFG: debug - compiler: msvc ARCH: x86 + VCPKG_ARCH: x86-windows CFG: debug - compiler: msys2 @@ -27,11 +31,18 @@ environment: install: - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" -build_script: - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' + - 'if "%compiler%"=="msvc" git clone https://github.com/Microsoft/vcpkg' + - 'if "%compiler%"=="msvc" cd vcpkg' + - 'if "%compiler%"=="msvc" powershell -exec bypass scripts\bootstrap.ps1' + - 'if "%compiler%"=="msvc" vcpkg install freetype:%VCPKG_ARCH%' + - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib" + - 'if "%compiler%"=="msvc" cd ..' + +build_script: - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32' - - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"' From c3fa5d0e03b57be131c66ea8720806c946d0e10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Mon, 24 Oct 2016 21:42:04 +0200 Subject: [PATCH 0087/1326] Remove inexistent file ttx file from test/api/Makefile.am --- test/api/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/test/api/Makefile.am b/test/api/Makefile.am index d514a6f82..530bf3ede 100644 --- a/test/api/Makefile.am +++ b/test/api/Makefile.am @@ -57,7 +57,6 @@ test_ot_math_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS) EXTRA_DIST += \ fonts/MathTestFontEmpty.otf \ fonts/MathTestFontFull.otf \ - fonts/MathTestFontFull.ttx \ fonts/MathTestFontNone.otf \ fonts/MathTestFontPartial1.otf \ fonts/MathTestFontPartial2.otf \ From 0e79ebb3ca9b7b6d238a0007e5ca022845ee9afc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 23 Oct 2016 14:39:43 +0200 Subject: [PATCH 0088/1326] [gobject] Update for new MATH structs --- src/hb-gobject-structs.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-gobject-structs.cc b/src/hb-gobject-structs.cc index 6bd63368b..fef00245b 100644 --- a/src/hb-gobject-structs.cc +++ b/src/hb-gobject-structs.cc @@ -78,3 +78,6 @@ HB_DEFINE_VALUE_TYPE (glyph_info) HB_DEFINE_VALUE_TYPE (glyph_position) HB_DEFINE_VALUE_TYPE (segment_properties) HB_DEFINE_VALUE_TYPE (user_data_key) + +HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant) +HB_DEFINE_VALUE_TYPE (ot_math_glyph_part) From b6c765871b752c9436ec993e47b48f9d4fecaed5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 10:33:33 +0200 Subject: [PATCH 0089/1326] [ci] Fix appveyor.yml syntax error --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 06530007b..ddcc9a41a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,7 +36,7 @@ install: - 'if "%compiler%"=="msvc" cd vcpkg' - 'if "%compiler%"=="msvc" powershell -exec bypass scripts\bootstrap.ps1' - 'if "%compiler%"=="msvc" vcpkg install freetype:%VCPKG_ARCH%' - - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib" + - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib' - 'if "%compiler%"=="msvc" cd ..' build_script: From 118164293cc7eb18ba03896f602aff816400134b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 16:04:30 +0200 Subject: [PATCH 0090/1326] Fix "make distcheck" --- configure.ac | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 14c86b7c5..6f658cda6 100644 --- a/configure.ac +++ b/configure.ac @@ -9,8 +9,6 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([src/harfbuzz.pc.in]) AC_CONFIG_HEADERS([config.h]) -AC_USE_SYSTEM_EXTENSIONS - AM_INIT_AUTOMAKE([1.11.1 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability]) AM_CONDITIONAL(AUTOMAKE_OLDER_THAN_1_13, test $am__api_version = 1.11 -o $am__api_version = 1.12) AM_SILENT_RULES([yes]) @@ -21,6 +19,7 @@ LT_PREREQ([2.2]) LT_INIT([disable-static]) # Check for programs +AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AM_PROG_CC_C_O AC_PROG_CXX From 966ac7ecd3d0128a3adacdd26aacef2bd8afa4d4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 16:17:15 +0200 Subject: [PATCH 0091/1326] 1.3.3 --- NEWS | 24 ++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ae0926e63..e83f25f2b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,27 @@ +Overview of changes leading to 1.3.3 +Wednesday, September 28, 2016 +==================================== + +- Implement parsing of OpenType MATH table. +New API: +HB_OT_TAG_MATH +HB_OT_MATH_SCRIPT +hb_ot_math_constant_t +hb_ot_math_kern_t +hb_ot_math_glyph_variant_t +hb_ot_math_glyph_part_flags_t +hb_ot_math_glyph_part_t +hb_ot_math_has_data +hb_ot_math_get_constant +hb_ot_math_get_glyph_italics_correction +hb_ot_math_get_glyph_top_accent_attachment +hb_ot_math_get_glyph_kerning +hb_ot_math_is_glyph_extended_shape +hb_ot_math_get_glyph_variants +hb_ot_math_get_min_connector_overlap +hb_ot_math_get_glyph_assembly + + Overview of changes leading to 1.3.2 Wednesday, September 27, 2016 ==================================== diff --git a/configure.ac b/configure.ac index 6f658cda6..b38ba98c7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.3.2], + [1.3.3], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From b3b0816d5fc00298621f738cf400de60f8a42c5d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 17:19:07 +0200 Subject: [PATCH 0092/1326] Fix vertical font metrics Ouch! --- src/hb-font-private.hh | 4 ++-- src/hb-ot-font.cc | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 6d5012ec1..99a865660 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -303,14 +303,14 @@ struct hb_font_t { if (!get_font_h_extents (extents)) { extents->ascender = y_scale * .8; - extents->descender = y_scale - extents->ascender; + extents->descender = extents->ascender - y_scale; extents->line_gap = 0; } } else { if (!get_font_v_extents (extents)) { extents->ascender = x_scale / 2; - extents->descender = x_scale - extents->ascender; + extents->descender = extents->ascender - x_scale; extents->line_gap = 0; } } diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 0b7e31b2d..9fd8d0502 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -47,6 +47,7 @@ struct hb_ot_face_metrics_accelerator_t unsigned short ascender; unsigned short descender; unsigned short line_gap; + bool has_font_extents; const OT::_mtx *table; hb_blob_t *blob; @@ -82,9 +83,12 @@ struct hb_ot_face_metrics_accelerator_t this->ascender = _hea->ascender; this->descender = _hea->descender; this->line_gap = _hea->lineGap; + got_font_extents = (this->ascender | this->descender) != 0; } hb_blob_destroy (_hea_blob); + this->has_font_extents = got_font_extents; + this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); /* Cap num_metrics() and num_advances() based on table length. */ @@ -475,7 +479,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); - return true; + return ot_font->h_metrics.has_font_extents; } static hb_bool_t @@ -488,7 +492,7 @@ hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); - return true; + return ot_font->v_metrics.has_font_extents; } static hb_font_funcs_t *static_ot_funcs = NULL; From 9ee23c49a7a7b2479ae0d36a64720e92eb8a36e7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 17:44:16 +0200 Subject: [PATCH 0093/1326] Fix vertical glyph origin with hb-ot-font --- src/hb-font-private.hh | 51 ++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 99a865660..91d4a587f 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -339,30 +339,37 @@ struct hb_font_t { *y = y_scale; } + inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + if (!get_glyph_h_origin (glyph, x, y) && + get_glyph_v_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x -= dx; *y -= dy; + } + } + inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, + hb_position_t *x, hb_position_t *y) + { + if (!get_glyph_v_origin (glyph, x, y) && + get_glyph_h_origin (glyph, x, y)) + { + hb_position_t dx, dy; + guess_v_origin_minus_h_origin (glyph, &dx, &dy); + *x += dx; *y += dy; + } + } + inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, hb_direction_t direction, hb_position_t *x, hb_position_t *y) { if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) - { - if (!get_glyph_h_origin (glyph, x, y) && - get_glyph_v_origin (glyph, x, y)) - { - hb_position_t dx, dy; - guess_v_origin_minus_h_origin (glyph, &dx, &dy); - *x -= dx; *y -= dy; - } - } + get_glyph_h_origin_with_fallback (glyph, x, y); else - { - if (!get_glyph_v_origin (glyph, x, y) && - get_glyph_h_origin (glyph, x, y)) - { - hb_position_t dx, dy; - guess_v_origin_minus_h_origin (glyph, &dx, &dy); - *x += dx; *y += dy; - } - } + get_glyph_v_origin_with_fallback (glyph, x, y); } inline void add_glyph_h_origin (hb_codepoint_t glyph, @@ -370,7 +377,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_h_origin (glyph, &origin_x, &origin_y); + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); *x += origin_x; *y += origin_y; @@ -380,7 +387,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_v_origin (glyph, &origin_x, &origin_y); + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); *x += origin_x; *y += origin_y; @@ -402,7 +409,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_h_origin (glyph, &origin_x, &origin_y); + get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); *x -= origin_x; *y -= origin_y; @@ -412,7 +419,7 @@ struct hb_font_t { { hb_position_t origin_x, origin_y; - get_glyph_v_origin (glyph, &origin_x, &origin_y); + get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); *x -= origin_x; *y -= origin_y; From 63635c763dd9393df236f49d491510cca18a1ccc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 17:54:04 +0200 Subject: [PATCH 0094/1326] [hb-ot-font] Use ascent+descent as fallback vertical advance --- src/hb-ot-font.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 9fd8d0502..20f2f8944 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -55,9 +55,10 @@ struct hb_ot_face_metrics_accelerator_t inline void init (hb_face_t *face, hb_tag_t _hea_tag, hb_tag_t _mtx_tag, - hb_tag_t os2_tag) + hb_tag_t os2_tag, + unsigned int default_advance = 0) { - this->default_advance = face->get_upem (); + this->default_advance = default_advance ? default_advance : face->get_upem (); bool got_font_extents = false; if (os2_tag) @@ -391,7 +392,8 @@ _hb_ot_font_create (hb_face_t *face) ot_font->cmap.init (face); ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */ + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE, + ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); return ot_font; From a7b32f2057098012b3ab43121397766ae45b3559 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 18:08:41 +0200 Subject: [PATCH 0095/1326] Move code around --- src/hb-font-private.hh | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 91d4a587f..324cadc1a 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -296,24 +296,32 @@ struct hb_font_t { /* A bit higher-level, and with fallback */ + inline void get_h_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_h_extents (extents)) + { + extents->ascender = y_scale * .8; + extents->descender = extents->ascender - y_scale; + extents->line_gap = 0; + } + } + inline void get_v_extents_with_fallback (hb_font_extents_t *extents) + { + if (!get_font_v_extents (extents)) + { + extents->ascender = x_scale / 2; + extents->descender = extents->ascender - x_scale; + extents->line_gap = 0; + } + } + inline void get_extents_for_direction (hb_direction_t direction, hb_font_extents_t *extents) { - if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { - if (!get_font_h_extents (extents)) - { - extents->ascender = y_scale * .8; - extents->descender = extents->ascender - y_scale; - extents->line_gap = 0; - } - } else { - if (!get_font_v_extents (extents)) - { - extents->ascender = x_scale / 2; - extents->descender = extents->ascender - x_scale; - extents->line_gap = 0; - } - } + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) + get_h_extents_with_fallback (extents); + else + get_v_extents_with_fallback (extents); } inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, From 2b117720c03869c7714304fd7fbfb2b01199bb3a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 18:12:50 +0200 Subject: [PATCH 0096/1326] Use horizontal ascent as fallback vertical origin --- src/hb-font-private.hh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 324cadc1a..cda97a68c 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -337,14 +337,15 @@ struct hb_font_t { } } - /* Internal only */ inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = get_glyph_h_advance (glyph) / 2; - /* TODO use font_extents.ascender */ - *y = y_scale; + /* TODO cache this somehow?! */ + hb_font_extents_t extents; + get_h_extents_with_fallback (&extents); + *y = extents.ascender; } inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, From d163cd956246449e3e48b54ce6eb5cdb14e3a0a6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 26 Oct 2016 18:27:48 +0200 Subject: [PATCH 0097/1326] [tests] Add tests for vertical origin with ft and ot font-funcs --- .../f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf | Bin 0 -> 1004 bytes test/shaping/tests/vertical.tests | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf diff --git a/test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf b/test/shaping/fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ed2fab9ef322b80ccfa0b952235b092cb53688c2 GIT binary patch literal 1004 zcmZvaUr5tY6vw~!{(e85bGg(hMrd0T4H63fJ)~3)b<%^DE07Y}ueCqrHrKXbLQxjM zh!!REB8CJZS&@4XvD`y~;zRUcFFh3W;Hy+fL227McRv%0?vHzZ=X38l_kPdef&nPP zbx3g9+dDe3lRQY(v|4UI-s8CD8MhI)636Y1Q?{mu-M5Grh--Qr2kNh^MB)IiBX+t1 zY6u2gCcZ;l=T##i=#WqG6~qRwf5>y>;Fn_ZS7|1FZuR_6cIFbm#Cgp=S}2<0E0nJz zuJ#3@F=Hj8^Vu(AgMZMa!h$~H6tOO##zJtiY2qcuPGGQkgJPCxFfvP`hWOpB6QZ|6QX z_aWxWbWm@W0C`cFfe{s?1*I0VTxQD4FDoxEGs#v|P>=!b}7#{LtD7hPwKt=~~7+6T;!Hm-^PyM1rgHWKM&{fO=yVS&~M zs^cx@l}hSJ164(5=o0BCfPQ8pu|BLH`R6`T0$HAA_ecqpQOW_^qy432csO*N7b;v< zWX@%}MQGX@_MRR)j-m}V?G9an_nE=QKfNav$Ecft8CsTBmx0Jkt1^A!BwIF1wk?~@ zzTP^Sqlz>!xqwzmXjk(&z2*{hV-QiAW;mcChzNS&hL_%^pE#V0CIe(W;(h#QFzS*H zobLUjNDJb*`!y?+>0v`ZB-c>b50f|S9)Q`eMuVu!)dR{GQKB}@XWM)ZX}}#0!nEB| qpvVw$1*CxGrg*u+7kv?XB{YRXve{L#LdRZI|E0r}(_x~$&G8$?ptw2! literal 0 HcmV?d00001 diff --git a/test/shaping/tests/vertical.tests b/test/shaping/tests/vertical.tests index 827689088..3586080f8 100644 --- a/test/shaping/tests/vertical.tests +++ b/test/shaping/tests/vertical.tests @@ -1 +1,3 @@ fonts/sha1sum/191826b9643e3f124d865d617ae609db6a2ce203.ttf:--direction=t:U+300C:[uni300C.vert=0@-512,-578+0,-1024] +fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ft:U+0041,U+0042:[gid1=0@-654,-2128+0,-2789|gid2=1@-665,-2125+0,-2789] +fonts/sha1sum/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-2189+0,-2789|gid2=1@-665,-2189+0,-2789] From 261837e7202ec584f653f379851e1c6457396b07 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 28 Oct 2016 21:49:11 +0330 Subject: [PATCH 0098/1326] Fix "nmake install" when ADDITIONAL_LIB_DIR is provided and test it on CI (#356) --- appveyor.yml | 1 + win32/detectenv-msvc.mak | 4 ++-- win32/generate-msvc.mak | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ddcc9a41a..2a0e7c59f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,6 +43,7 @@ build_script: - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32' - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 install' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"' diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak index 41f4bd097..80a5eed7a 100644 --- a/win32/detectenv-msvc.mak +++ b/win32/detectenv-msvc.mak @@ -129,10 +129,10 @@ LDFLAGS_ARCH = /machine:x86 !if "$(VALID_CFGSET)" == "TRUE" CFLAGS = $(CFLAGS_ADD) /W3 /Zi /I.. /I..\src /I. /I$(PREFIX)\include -LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib /DEBUG !if "$(ADDITIONAL_LIB_DIR)" != "" -LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(ADDITIONAL_LIB_DIR) +ADDITIONAL_LIB_ARG = /libpath:$(ADDITIONAL_LIB_DIR) !endif +LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib $(ADDITIONAL_LIB_ARG) /DEBUG !if "$(CFG)" == "debug" LDFLAGS = $(LDFLAGS_BASE) diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak index 7c17a9465..57cfb6ecb 100644 --- a/win32/generate-msvc.mak +++ b/win32/generate-msvc.mak @@ -23,4 +23,4 @@ $(HB_GOBJECT_ENUM_GENERATED_SOURCES): ..\src\hb-gobject-enums.h.tmpl ..\src\hb-g # Create the build directories $(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-icu $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util: - @-mkdir -p $@ + @-md $@ From 831852594b777f250efedb76d19bee1cfc8eeaa4 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Fri, 2 Dec 2016 15:03:50 -0800 Subject: [PATCH 0099/1326] Introduce get_extent support for color bitmap font. (#351) hb_font_get_glyph_extents now works for color bitmap fonts. Currently only font having index format 1 and image format 17 is supported. --- src/Makefile.sources | 1 + src/hb-ot-ebdt-table.hh | 193 ++++++++++++++++++++++++++++++++++++++++ src/hb-ot-font.cc | 96 ++++++++++++++++++++ 3 files changed, 290 insertions(+) create mode 100644 src/hb-ot-ebdt-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 5c695c5c2..8d2f3c681 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -21,6 +21,7 @@ HB_BASE_sources = \ hb-open-file-private.hh \ hb-open-type-private.hh \ hb-ot-cmap-table.hh \ + hb-ot-ebdt-table.hh \ hb-ot-glyf-table.hh \ hb-ot-head-table.hh \ hb-ot-hhea-table.hh \ diff --git a/src/hb-ot-ebdt-table.hh b/src/hb-ot-ebdt-table.hh new file mode 100644 index 000000000..f3d0de619 --- /dev/null +++ b/src/hb-ot-ebdt-table.hh @@ -0,0 +1,193 @@ +/* + * Copyright © 2016 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Seigo Nonaka + */ + +#ifndef HB_OT_EBDT_TABLE_HH +#define HB_OT_EBDT_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + +struct SmallGlyphMetrics +{ + BYTE height; + BYTE width; + int8_t bearingX; + int8_t bearingY; + BYTE advance; + + DEFINE_SIZE_STATIC(5); +}; + +struct SBitLineMetrics { + int8_t ascender; + int8_t decender; + BYTE widthMax; + int8_t caretSlopeNumerator; + int8_t caretSlopeDenominator; + int8_t caretOffset; + int8_t minOriginSB; + int8_t minAdvanceSB; + int8_t maxBeforeBL; + int8_t minAfterBL; + int8_t padding1; + int8_t padding2; + + DEFINE_SIZE_STATIC(12); +}; + +struct BitmapSizeTable +{ + ULONG indexSubtableArrayOffset; + ULONG indexTablesSize; + ULONG numberOfIndexSubtables; + ULONG colorRef; + SBitLineMetrics horizontal; + SBitLineMetrics vertical; + USHORT startGlyphIndex; + USHORT endGlyphIndex; + BYTE ppemX; + BYTE ppemY; + BYTE bitDepth; + int8_t flags; + + DEFINE_SIZE_STATIC(48); +}; + +/* + * Index Subtables. + */ +struct IndexSubtable +{ + USHORT firstGlyphIndex; + USHORT lastGlyphIndex; + ULONG offsetToSubtable; + + DEFINE_SIZE_STATIC(8); +}; + +struct IndexSubHeader +{ + USHORT indexFormat; + USHORT imageFormat; + ULONG imageDataOffset; +}; + +struct IndexSubtableFormat1 +{ + IndexSubHeader header; + ULONG offsetArray[VAR]; +}; + +/* + * Glyph Bitmap Data Formats. + */ +struct GlyphBitmapDataFormat17 +{ + SmallGlyphMetrics glyphMetrics; + ULONG dataLen; + BYTE data[VAR]; +}; + +struct IndexSubtableArray +{ + public: + const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const + { + for (unsigned int i = 0; i < numTables; ++i) { + unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex; + unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex; + if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) { + return &indexSubtables[i]; + } + } + return NULL; + } + + protected: + IndexSubtable indexSubtables[VAR]; +}; + +/* + * CBLC -- Color Bitmap Location Table + */ + +#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C') + +struct CBLC +{ + static const hb_tag_t tableTag = HB_OT_TAG_CBLC; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (true); + } + + public: + const BitmapSizeTable* find_table(hb_codepoint_t glyph) const + { + // TODO: Make it possible to select strike. + const uint32_t tableSize = numSizes; + for (uint32_t i = 0; i < tableSize; ++i) { + unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex; + unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex; + if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) { + return &sizeTables[i]; + } + } + return NULL; + } + + protected: + ULONG version; + ULONG numSizes; + + BitmapSizeTable sizeTables[VAR]; +}; + +/* + * CBDT -- Color Bitmap Data Table + */ +#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T') + +struct CBDT +{ + static const hb_tag_t tableTag = HB_OT_TAG_CBDT; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (true); + } + + protected: + BYTE data[VAR]; +}; + +} /* namespace OT */ + +#endif /* HB_OT_EBDT_TABLE_HH */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 20f2f8944..d9be19690 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -31,6 +31,7 @@ #include "hb-font-private.hh" #include "hb-ot-cmap-table.hh" +#include "hb-ot-ebdt-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" @@ -207,6 +208,96 @@ struct hb_ot_face_glyf_accelerator_t } }; +struct hb_ot_face_ebdt_accelerator_t +{ + hb_blob_t *cblc_blob = NULL; + hb_blob_t *cbdt_blob = NULL; + const OT::CBLC *cblc = NULL; + const OT::CBDT *cbdt = NULL; + + float upem = 0.0f; + + inline void init (hb_face_t *face) + { + this->cblc_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBLC)); + this->cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT)); + + if (hb_blob_get_length (this->cblc_blob) == 0) { + return; /* Not a bitmap font. */ + } + cblc = OT::Sanitizer::lock_instance (this->cblc_blob); + cbdt = OT::Sanitizer::lock_instance (this->cbdt_blob); + + upem = face->get_upem(); + } + + inline void fini (void) + { + if (this->cblc_blob) { + hb_blob_destroy (this->cblc_blob); + hb_blob_destroy (this->cbdt_blob); + } + } + + inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + { + if (cblc == NULL) { + return false; // Not a color bitmap font. + } + + const OT::BitmapSizeTable* sizeTable = this->cblc->find_table(glyph); + if (sizeTable == NULL) { + return false; + } + + const OT::IndexSubtableArray& subtables = + OT::StructAtOffset (this->cblc, sizeTable->indexSubtableArrayOffset); + const OT::IndexSubtable* subtable = subtables.find_table(glyph, sizeTable->numberOfIndexSubtables); + if (subtable == NULL) { + return false; + } + + unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable; + const OT::IndexSubHeader& header = + OT::StructAtOffset (this->cblc, offsetToSubtable); + + unsigned int imageDataOffset = header.imageDataOffset; + switch (header.indexFormat) { + case 1: { + const OT::IndexSubtableFormat1& format1 = + OT::StructAtOffset (this->cblc, offsetToSubtable); + imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex]; + switch (header.imageFormat) { + case 17: { + const OT::GlyphBitmapDataFormat17& glyphFormat17 = + OT::StructAtOffset (this->cbdt, imageDataOffset); + extents->x_bearing = glyphFormat17.glyphMetrics.bearingX; + extents->y_bearing = glyphFormat17.glyphMetrics.bearingY; + extents->width = glyphFormat17.glyphMetrics.width; + extents->height = -glyphFormat17.glyphMetrics.height; + } + break; + default: + // TODO: Support other image formats. + return false; + } + } + break; + default: + // TODO: Support other index subtable format. + return false; + } + + // Convert to the font units. + extents->x_bearing *= upem / (float)(sizeTable->ppemX); + extents->y_bearing *= upem / (float)(sizeTable->ppemY); + extents->width *= upem / (float)(sizeTable->ppemX); + extents->height *= upem / (float)(sizeTable->ppemY); + + return true; + } +}; + typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph); @@ -379,6 +470,7 @@ struct hb_ot_font_t hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; hb_lazy_loader_t glyf; + hb_lazy_loader_t ebdt; }; @@ -395,6 +487,7 @@ _hb_ot_font_create (hb_face_t *face) ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); + ot_font->ebdt.init (face); return ot_font; } @@ -406,6 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font) ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); ot_font->glyf.fini (); + ot_font->ebdt.fini (); free (ot_font); } @@ -464,6 +558,8 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; bool ret = ot_font->glyf->get_extents (glyph, extents); + if ( !ret ) + ret = ot_font->ebdt->get_extents (glyph, extents); extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->width = font->em_scale_x (extents->width); From efca7bf97f9967af4fa399a6665b723af643cecd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 15:11:37 -0800 Subject: [PATCH 0100/1326] Rename 'ebdt' to 'cbdt' since we only support the PNG format --- src/Makefile.sources | 2 +- src/{hb-ot-ebdt-table.hh => hb-ot-cbdt-table.hh} | 6 +++--- src/hb-ot-font.cc | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) rename src/{hb-ot-ebdt-table.hh => hb-ot-cbdt-table.hh} (97%) diff --git a/src/Makefile.sources b/src/Makefile.sources index 8d2f3c681..166793aa4 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -20,8 +20,8 @@ HB_BASE_sources = \ hb-object-private.hh \ hb-open-file-private.hh \ hb-open-type-private.hh \ + hb-ot-cbdt-table.hh \ hb-ot-cmap-table.hh \ - hb-ot-ebdt-table.hh \ hb-ot-glyf-table.hh \ hb-ot-head-table.hh \ hb-ot-hhea-table.hh \ diff --git a/src/hb-ot-ebdt-table.hh b/src/hb-ot-cbdt-table.hh similarity index 97% rename from src/hb-ot-ebdt-table.hh rename to src/hb-ot-cbdt-table.hh index f3d0de619..17f15dc4f 100644 --- a/src/hb-ot-ebdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -24,8 +24,8 @@ * Google Author(s): Seigo Nonaka */ -#ifndef HB_OT_EBDT_TABLE_HH -#define HB_OT_EBDT_TABLE_HH +#ifndef HB_OT_CBDT_TABLE_HH +#define HB_OT_CBDT_TABLE_HH #include "hb-open-type-private.hh" @@ -190,4 +190,4 @@ struct CBDT } /* namespace OT */ -#endif /* HB_OT_EBDT_TABLE_HH */ +#endif /* HB_OT_CBDT_TABLE_HH */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index d9be19690..c53fcd519 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -31,7 +31,7 @@ #include "hb-font-private.hh" #include "hb-ot-cmap-table.hh" -#include "hb-ot-ebdt-table.hh" +#include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-head-table.hh" #include "hb-ot-hhea-table.hh" @@ -208,7 +208,7 @@ struct hb_ot_face_glyf_accelerator_t } }; -struct hb_ot_face_ebdt_accelerator_t +struct hb_ot_face_cbdt_accelerator_t { hb_blob_t *cblc_blob = NULL; hb_blob_t *cbdt_blob = NULL; @@ -470,7 +470,7 @@ struct hb_ot_font_t hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; hb_lazy_loader_t glyf; - hb_lazy_loader_t ebdt; + hb_lazy_loader_t cbdt; }; @@ -487,7 +487,7 @@ _hb_ot_font_create (hb_face_t *face) ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); - ot_font->ebdt.init (face); + ot_font->cbdt.init (face); return ot_font; } @@ -499,7 +499,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font) ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); ot_font->glyf.fini (); - ot_font->ebdt.fini (); + ot_font->cbdt.fini (); free (ot_font); } @@ -559,7 +559,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; bool ret = ot_font->glyf->get_extents (glyph, extents); if ( !ret ) - ret = ot_font->ebdt->get_extents (glyph, extents); + ret = ot_font->cbdt->get_extents (glyph, extents); extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->width = font->em_scale_x (extents->width); From b92ba7bafcd9545a401fb871eb342e6284032c47 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 15:21:43 -0800 Subject: [PATCH 0101/1326] [CBDT] Use CHAR instead of int8_t --- src/hb-open-type-private.hh | 1 + src/hb-ot-cbdt-table.hh | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index df683ca4b..6b643784e 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -650,6 +650,7 @@ struct IntType DEFINE_SIZE_STATIC (Size); }; +typedef IntType CHAR; /* 8-bit signed integer. */ typedef IntType BYTE; /* 8-bit unsigned integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 17f15dc4f..7615138f5 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -35,26 +35,26 @@ struct SmallGlyphMetrics { BYTE height; BYTE width; - int8_t bearingX; - int8_t bearingY; + CHAR bearingX; + CHAR bearingY; BYTE advance; DEFINE_SIZE_STATIC(5); }; struct SBitLineMetrics { - int8_t ascender; - int8_t decender; + CHAR ascender; + CHAR decender; BYTE widthMax; - int8_t caretSlopeNumerator; - int8_t caretSlopeDenominator; - int8_t caretOffset; - int8_t minOriginSB; - int8_t minAdvanceSB; - int8_t maxBeforeBL; - int8_t minAfterBL; - int8_t padding1; - int8_t padding2; + CHAR caretSlopeNumerator; + CHAR caretSlopeDenominator; + CHAR caretOffset; + CHAR minOriginSB; + CHAR minAdvanceSB; + CHAR maxBeforeBL; + CHAR minAfterBL; + CHAR padding1; + CHAR padding2; DEFINE_SIZE_STATIC(12); }; @@ -72,7 +72,7 @@ struct BitmapSizeTable BYTE ppemX; BYTE ppemY; BYTE bitDepth; - int8_t flags; + CHAR flags; DEFINE_SIZE_STATIC(48); }; From 4b58c9e326acde09d389c699014e4e7f6259f50a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 19:25:54 -0800 Subject: [PATCH 0102/1326] [cbdt] Start fixing sanitization (or lack thereof) --- src/hb-ot-cbdt-table.hh | 77 ++++++++++++++++++++++++++++++----------- src/hb-ot-font.cc | 22 ++++++------ 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 7615138f5..dda42f257 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -33,6 +33,12 @@ namespace OT { struct SmallGlyphMetrics { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + BYTE height; BYTE width; CHAR bearingX; @@ -42,7 +48,14 @@ struct SmallGlyphMetrics DEFINE_SIZE_STATIC(5); }; -struct SBitLineMetrics { +struct SBitLineMetrics +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + CHAR ascender; CHAR decender; BYTE widthMax; @@ -61,6 +74,14 @@ struct SBitLineMetrics { struct BitmapSizeTable { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + horizontal.sanitize (c) && + vertical.sanitize (c)); + } + ULONG indexSubtableArrayOffset; ULONG indexTablesSize; ULONG numberOfIndexSubtables; @@ -94,41 +115,49 @@ struct IndexSubHeader USHORT indexFormat; USHORT imageFormat; ULONG imageDataOffset; + + DEFINE_SIZE_STATIC(8); }; struct IndexSubtableFormat1 { IndexSubHeader header; - ULONG offsetArray[VAR]; + ULONG offsetArrayZ[VAR]; + + DEFINE_SIZE_ARRAY(8, offsetArrayZ); }; /* * Glyph Bitmap Data Formats. */ + struct GlyphBitmapDataFormat17 { SmallGlyphMetrics glyphMetrics; ULONG dataLen; - BYTE data[VAR]; + BYTE dataZ[VAR]; + + DEFINE_SIZE_ARRAY(9, dataZ); }; struct IndexSubtableArray { public: - const IndexSubtable* find_table(hb_codepoint_t glyph, unsigned int numTables) const + const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const { - for (unsigned int i = 0; i < numTables; ++i) { - unsigned int firstGlyphIndex = indexSubtables[i].firstGlyphIndex; - unsigned int lastGlyphIndex = indexSubtables[i].lastGlyphIndex; + for (unsigned int i = 0; i < numTables; ++i) + { + unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex; + unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex; if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) { - return &indexSubtables[i]; + return &indexSubtablesZ[i]; } } return NULL; } protected: - IndexSubtable indexSubtables[VAR]; + IndexSubtable indexSubtablesZ[VAR]; }; /* @@ -144,17 +173,19 @@ struct CBLC inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (true); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3) && + sizeTables.sanitize (c)); } public: - const BitmapSizeTable* find_table(hb_codepoint_t glyph) const + const BitmapSizeTable* find_table (hb_codepoint_t glyph) const { // TODO: Make it possible to select strike. - const uint32_t tableSize = numSizes; - for (uint32_t i = 0; i < tableSize; ++i) { - unsigned int startGlyphIndex = sizeTables[i].startGlyphIndex; - unsigned int endGlyphIndex = sizeTables[i].endGlyphIndex; + unsigned int count = sizeTables.len; + for (uint32_t i = 0; i < count; ++i) { + unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex; + unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex; if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) { return &sizeTables[i]; } @@ -163,10 +194,11 @@ struct CBLC } protected: - ULONG version; - ULONG numSizes; + FixedVersion<>version; + ArrayOf sizeTables; - BitmapSizeTable sizeTables[VAR]; + public: + DEFINE_SIZE_ARRAY(8, sizeTables); }; /* @@ -181,11 +213,16 @@ struct CBDT inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (true); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3)); } protected: - BYTE data[VAR]; + FixedVersion<>version; + BYTE dataZ[VAR]; + + public: + DEFINE_SIZE_ARRAY(4, dataZ); }; } /* namespace OT */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index c53fcd519..25a1ef6c3 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -210,10 +210,10 @@ struct hb_ot_face_glyf_accelerator_t struct hb_ot_face_cbdt_accelerator_t { - hb_blob_t *cblc_blob = NULL; - hb_blob_t *cbdt_blob = NULL; - const OT::CBLC *cblc = NULL; - const OT::CBDT *cbdt = NULL; + hb_blob_t *cblc_blob; + hb_blob_t *cbdt_blob; + const OT::CBLC *cblc; + const OT::CBDT *cbdt; float upem = 0.0f; @@ -223,6 +223,8 @@ struct hb_ot_face_cbdt_accelerator_t this->cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT)); if (hb_blob_get_length (this->cblc_blob) == 0) { + cblc = NULL; + cbdt = NULL; return; /* Not a bitmap font. */ } cblc = OT::Sanitizer::lock_instance (this->cblc_blob); @@ -233,10 +235,8 @@ struct hb_ot_face_cbdt_accelerator_t inline void fini (void) { - if (this->cblc_blob) { - hb_blob_destroy (this->cblc_blob); - hb_blob_destroy (this->cbdt_blob); - } + hb_blob_destroy (this->cblc_blob); + hb_blob_destroy (this->cbdt_blob); } inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const @@ -266,7 +266,7 @@ struct hb_ot_face_cbdt_accelerator_t case 1: { const OT::IndexSubtableFormat1& format1 = OT::StructAtOffset (this->cblc, offsetToSubtable); - imageDataOffset += format1.offsetArray[glyph - subtable->firstGlyphIndex]; + imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex]; switch (header.imageFormat) { case 17: { const OT::GlyphBitmapDataFormat17& glyphFormat17 = @@ -288,7 +288,7 @@ struct hb_ot_face_cbdt_accelerator_t return false; } - // Convert to the font units. + /* Convert to the font units. */ extents->x_bearing *= upem / (float)(sizeTable->ppemX); extents->y_bearing *= upem / (float)(sizeTable->ppemY); extents->width *= upem / (float)(sizeTable->ppemX); @@ -558,7 +558,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; bool ret = ot_font->glyf->get_extents (glyph, extents); - if ( !ret ) + if (!ret) ret = ot_font->cbdt->get_extents (glyph, extents); extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); From 70eb2ff682344688635cebb716fee0b73557c925 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 19:51:23 -0800 Subject: [PATCH 0103/1326] Check for offset overflows during sanitize --- src/hb-open-type-private.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 6b643784e..66f1c08df 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -806,6 +806,7 @@ struct OffsetTo : Offset if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; if (unlikely (!offset)) return_trace (true); + if (unlikely (!c->check_range (base, offset))) return_trace (false); const Type &obj = StructAtOffset (base, offset); return_trace (likely (obj.sanitize (c)) || neuter (c)); } @@ -816,6 +817,7 @@ struct OffsetTo : Offset if (unlikely (!c->check_struct (this))) return_trace (false); unsigned int offset = *this; if (unlikely (!offset)) return_trace (true); + if (unlikely (!c->check_range (base, offset))) return_trace (false); const Type &obj = StructAtOffset (base, offset); return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); } From ce09e90e1502d5f944bafd64e51c29e365a963ae Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 20:12:57 -0800 Subject: [PATCH 0104/1326] [cbdt] More sanitize work --- src/hb-ot-cbdt-table.hh | 65 ++++++++++++++++++++++++----------------- src/hb-ot-font.cc | 46 ++++++++++++++++------------- 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index dda42f257..3a7cc997d 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -72,32 +72,6 @@ struct SBitLineMetrics DEFINE_SIZE_STATIC(12); }; -struct BitmapSizeTable -{ - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - horizontal.sanitize (c) && - vertical.sanitize (c)); - } - - ULONG indexSubtableArrayOffset; - ULONG indexTablesSize; - ULONG numberOfIndexSubtables; - ULONG colorRef; - SBitLineMetrics horizontal; - SBitLineMetrics vertical; - USHORT startGlyphIndex; - USHORT endGlyphIndex; - BYTE ppemX; - BYTE ppemY; - BYTE bitDepth; - CHAR flags; - - DEFINE_SIZE_STATIC(48); -}; - /* * Index Subtables. */ @@ -142,6 +116,12 @@ struct GlyphBitmapDataFormat17 struct IndexSubtableArray { + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); // XXX + } + public: const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const { @@ -158,6 +138,37 @@ struct IndexSubtableArray protected: IndexSubtable indexSubtablesZ[VAR]; + + public: + DEFINE_SIZE_ARRAY(0, indexSubtablesZ); +}; + +struct BitmapSizeTable +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) && + c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) && + horizontal.sanitize (c) && + vertical.sanitize (c)); + } + + OffsetTo indexSubtableArrayOffset; + ULONG indexTablesSize; + ULONG numberOfIndexSubtables; + ULONG colorRef; + SBitLineMetrics horizontal; + SBitLineMetrics vertical; + USHORT startGlyphIndex; + USHORT endGlyphIndex; + BYTE ppemX; + BYTE ppemY; + BYTE bitDepth; + CHAR flags; + + DEFINE_SIZE_STATIC(48); }; /* @@ -175,7 +186,7 @@ struct CBLC TRACE_SANITIZE (this); return_trace (c->check_struct (this) && likely (version.major == 2 || version.major == 3) && - sizeTables.sanitize (c)); + sizeTables.sanitize (c, this)); } public: diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 25a1ef6c3..2d1cf09a7 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -262,30 +262,34 @@ struct hb_ot_face_cbdt_accelerator_t OT::StructAtOffset (this->cblc, offsetToSubtable); unsigned int imageDataOffset = header.imageDataOffset; - switch (header.indexFormat) { - case 1: { - const OT::IndexSubtableFormat1& format1 = - OT::StructAtOffset (this->cblc, offsetToSubtable); - imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex]; - switch (header.imageFormat) { - case 17: { - const OT::GlyphBitmapDataFormat17& glyphFormat17 = - OT::StructAtOffset (this->cbdt, imageDataOffset); - extents->x_bearing = glyphFormat17.glyphMetrics.bearingX; - extents->y_bearing = glyphFormat17.glyphMetrics.bearingY; - extents->width = glyphFormat17.glyphMetrics.width; - extents->height = -glyphFormat17.glyphMetrics.height; - } - break; - default: - // TODO: Support other image formats. - return false; - } + switch (header.indexFormat) + { + case 1: + { + const OT::IndexSubtableFormat1& format1 = + OT::StructAtOffset (this->cblc, offsetToSubtable); + imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex]; + } + break; + default: + // TODO: Support other index subtable format. + return false; + } + + switch (header.imageFormat) + { + case 17: { + const OT::GlyphBitmapDataFormat17& glyphFormat17 = + OT::StructAtOffset (this->cbdt, imageDataOffset); + extents->x_bearing = glyphFormat17.glyphMetrics.bearingX; + extents->y_bearing = glyphFormat17.glyphMetrics.bearingY; + extents->width = glyphFormat17.glyphMetrics.width; + extents->height = -glyphFormat17.glyphMetrics.height; } break; default: - // TODO: Support other index subtable format. - return false; + // TODO: Support other image formats. + return false; } /* Convert to the font units. */ From d495fc5e38038f4cfb20425b1109324fa70bf2f9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 21:36:42 -0800 Subject: [PATCH 0105/1326] [cbdt] Clean up some more Almost there.. --- src/hb-ot-cbdt-table.hh | 134 +++++++++++++++++++++++++++++++++++----- src/hb-ot-font.cc | 38 ++++-------- 2 files changed, 131 insertions(+), 41 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 3a7cc997d..431906775 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -39,6 +39,14 @@ struct SmallGlyphMetrics return_trace (c->check_struct (this)); } + inline void get_extents (hb_glyph_extents_t *extents) const + { + extents->x_bearing = bearingX; + extents->y_bearing = bearingY; + extents->width = width; + extents->height = height; + } + BYTE height; BYTE width; CHAR bearingX; @@ -75,17 +83,14 @@ struct SBitLineMetrics /* * Index Subtables. */ -struct IndexSubtable +struct IndexSubtableHeader { - USHORT firstGlyphIndex; - USHORT lastGlyphIndex; - ULONG offsetToSubtable; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } - DEFINE_SIZE_STATIC(8); -}; - -struct IndexSubHeader -{ USHORT indexFormat; USHORT imageFormat; ULONG imageDataOffset; @@ -95,12 +100,108 @@ struct IndexSubHeader struct IndexSubtableFormat1 { - IndexSubHeader header; - ULONG offsetArrayZ[VAR]; + inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1)); + } + + bool get_image_data (unsigned int idx, + unsigned int *offset, + unsigned int *length) const + { + if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx])) + return false; + + *offset = header.imageDataOffset + offsetArrayZ[idx]; + *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx]; + return true; + } + + IndexSubtableHeader header; + Offset offsetArrayZ[VAR]; DEFINE_SIZE_ARRAY(8, offsetArrayZ); }; +struct IndexSubtable +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const + { + TRACE_SANITIZE (this); + if (!u.header.sanitize (c)) return_trace (false); + switch (u.header.indexFormat) { + case 1: return_trace (u.format1.sanitize (c, glyph_count)); + default:return_trace (true); + } + } + + inline bool get_extents (hb_glyph_extents_t *extents) const + { + switch (u.header.indexFormat) { + case 2: case 5: /* TODO */ + case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */ + default:return (false); + } + } + + bool get_image_data (unsigned int idx, + unsigned int *offset, + unsigned int *length, + unsigned int *format) const + { + *format = u.header.imageFormat; + switch (u.header.indexFormat) { + case 1: return u.format1.get_image_data (idx, offset, length); + default: return false; + } + } + + protected: + union { + IndexSubtableHeader header; + IndexSubtableFormat1 format1; + } u; + public: + DEFINE_SIZE_UNION (8, header); +}; + +struct IndexSubtableRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + firstGlyphIndex <= lastGlyphIndex && + offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1)); + } + + inline bool get_extents (hb_glyph_extents_t *extents) const + { + return (this+offsetToSubtable).get_extents (extents); + } + + bool get_image_data (unsigned int gid, + unsigned int *offset, + unsigned int *length, + unsigned int *format) const + { + if (gid < firstGlyphIndex || gid > lastGlyphIndex) + { + return false; + } + return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, + offset, length, format); + } + + USHORT firstGlyphIndex; + USHORT lastGlyphIndex; + OffsetTo offsetToSubtable; + + DEFINE_SIZE_STATIC(8); +}; + /* * Glyph Bitmap Data Formats. */ @@ -119,11 +220,16 @@ struct IndexSubtableArray inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); // XXX + if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, sizeof (count)))) + return_trace (false); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!indexSubtablesZ[i].sanitize (c, this))) + return_trace (false); + return_trace (true); } public: - const IndexSubtable* find_table (hb_codepoint_t glyph, unsigned int numTables) const + const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const { for (unsigned int i = 0; i < numTables; ++i) { @@ -137,7 +243,7 @@ struct IndexSubtableArray } protected: - IndexSubtable indexSubtablesZ[VAR]; + IndexSubtableRecord indexSubtablesZ[VAR]; public: DEFINE_SIZE_ARRAY(0, indexSubtablesZ); diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 2d1cf09a7..5e02170f1 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -250,41 +250,25 @@ struct hb_ot_face_cbdt_accelerator_t return false; } - const OT::IndexSubtableArray& subtables = - OT::StructAtOffset (this->cblc, sizeTable->indexSubtableArrayOffset); - const OT::IndexSubtable* subtable = subtables.find_table(glyph, sizeTable->numberOfIndexSubtables); - if (subtable == NULL) { + const OT::IndexSubtableArray& subtables = this->cblc + sizeTable->indexSubtableArrayOffset; + const OT::IndexSubtableRecord *subtable_record = subtables.find_table (glyph, sizeTable->numberOfIndexSubtables); + if (subtable_record == NULL) { return false; } - unsigned int offsetToSubtable = sizeTable->indexSubtableArrayOffset + subtable->offsetToSubtable; - const OT::IndexSubHeader& header = - OT::StructAtOffset (this->cblc, offsetToSubtable); + if (subtable_record->get_extents (extents)) + return true; - unsigned int imageDataOffset = header.imageDataOffset; - switch (header.indexFormat) - { - case 1: - { - const OT::IndexSubtableFormat1& format1 = - OT::StructAtOffset (this->cblc, offsetToSubtable); - imageDataOffset += format1.offsetArrayZ[glyph - subtable->firstGlyphIndex]; - } - break; - default: - // TODO: Support other index subtable format. - return false; - } + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) + return false; - switch (header.imageFormat) + switch (image_format) { case 17: { const OT::GlyphBitmapDataFormat17& glyphFormat17 = - OT::StructAtOffset (this->cbdt, imageDataOffset); - extents->x_bearing = glyphFormat17.glyphMetrics.bearingX; - extents->y_bearing = glyphFormat17.glyphMetrics.bearingY; - extents->width = glyphFormat17.glyphMetrics.width; - extents->height = -glyphFormat17.glyphMetrics.height; + OT::StructAtOffset (this->cbdt, image_offset); + glyphFormat17.glyphMetrics.get_extents (extents); } break; default: From c27d6fcf8db6f02e075dd1868ae67d878fff39d4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 2 Dec 2016 22:43:05 -0800 Subject: [PATCH 0106/1326] [cbdt] Last of sanitization fixes Should be all good now.. --- src/hb-ot-font.cc | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 5e02170f1..1a2d3829e 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -215,22 +215,25 @@ struct hb_ot_face_cbdt_accelerator_t const OT::CBLC *cblc; const OT::CBDT *cbdt; - float upem = 0.0f; + unsigned int cbdt_len; + float upem; inline void init (hb_face_t *face) { - this->cblc_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBLC)); - this->cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT)); + upem = face->get_upem(); - if (hb_blob_get_length (this->cblc_blob) == 0) { + cblc_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBLC)); + cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT)); + cbdt_len = hb_blob_get_length (cbdt_blob); + + if (hb_blob_get_length (cblc_blob) == 0) { cblc = NULL; cbdt = NULL; return; /* Not a bitmap font. */ } - cblc = OT::Sanitizer::lock_instance (this->cblc_blob); - cbdt = OT::Sanitizer::lock_instance (this->cbdt_blob); + cblc = OT::Sanitizer::lock_instance (cblc_blob); + cbdt = OT::Sanitizer::lock_instance (cbdt_blob); - upem = face->get_upem(); } inline void fini (void) @@ -263,9 +266,15 @@ struct hb_ot_face_cbdt_accelerator_t if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) return false; + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) + return false; + switch (image_format) { case 17: { + if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size)) + return false; + const OT::GlyphBitmapDataFormat17& glyphFormat17 = OT::StructAtOffset (this->cbdt, image_offset); glyphFormat17.glyphMetrics.get_extents (extents); From 654f9ab0d8d5ee032b5da763e34e7b1f454416b9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 18:56:24 -0800 Subject: [PATCH 0107/1326] [cbdt] Fix sign bug Was introduced in d495fc5e38038f4cfb20425b1109324fa70bf2f9 --- src/hb-ot-cbdt-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 431906775..2043a2529 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -44,7 +44,7 @@ struct SmallGlyphMetrics extents->x_bearing = bearingX; extents->y_bearing = bearingY; extents->width = width; - extents->height = height; + extents->height = -height; } BYTE height; From 9eda74c92c9024ffb8ec6e9344c99d51dd763f0c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 19:12:52 -0800 Subject: [PATCH 0108/1326] [cbdt] Move some more code around --- src/hb-ot-cbdt-table.hh | 61 ++++++++++++++++++++++++++++------------- src/hb-ot-font.cc | 18 +++++------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 2043a2529..4770cf3f1 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -80,9 +80,11 @@ struct SBitLineMetrics DEFINE_SIZE_STATIC(12); }; + /* * Index Subtables. */ + struct IndexSubtableHeader { inline bool sanitize (hb_sanitize_context_t *c) const @@ -202,19 +204,6 @@ struct IndexSubtableRecord DEFINE_SIZE_STATIC(8); }; -/* - * Glyph Bitmap Data Formats. - */ - -struct GlyphBitmapDataFormat17 -{ - SmallGlyphMetrics glyphMetrics; - ULONG dataLen; - BYTE dataZ[VAR]; - - DEFINE_SIZE_ARRAY(9, dataZ); -}; - struct IndexSubtableArray { inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const @@ -251,6 +240,8 @@ struct IndexSubtableArray struct BitmapSizeTable { + friend struct CBLC; + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -261,6 +252,12 @@ struct BitmapSizeTable vertical.sanitize (c)); } + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const + { + return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); + } + + protected: OffsetTo indexSubtableArrayOffset; ULONG indexTablesSize; ULONG numberOfIndexSubtables; @@ -274,9 +271,25 @@ struct BitmapSizeTable BYTE bitDepth; CHAR flags; +public: DEFINE_SIZE_STATIC(48); }; + +/* + * Glyph Bitmap Data Formats. + */ + +struct GlyphBitmapDataFormat17 +{ + SmallGlyphMetrics glyphMetrics; + ULONG dataLen; + BYTE dataZ[VAR]; + + DEFINE_SIZE_ARRAY(9, dataZ); +}; + + /* * CBLC -- Color Bitmap Location Table */ @@ -296,18 +309,28 @@ struct CBLC } public: - const BitmapSizeTable* find_table (hb_codepoint_t glyph) const + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, + unsigned int *x_ppem, unsigned int *y_ppem) const { - // TODO: Make it possible to select strike. + /* TODO: Make it possible to select strike. */ + + const BitmapSizeTable *sizeTable = &Null(BitmapSizeTable); unsigned int count = sizeTables.len; - for (uint32_t i = 0; i < count; ++i) { + for (uint32_t i = 0; i < count; ++i) + { unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex; unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex; - if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) { - return &sizeTables[i]; + if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) + { + sizeTable = &sizeTables[i]; + break; } } - return NULL; + + *x_ppem = sizeTable->ppemX; + *y_ppem = sizeTable->ppemY; + + return sizeTable->find_table (glyph, this); } protected: diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 1a2d3829e..1b6cea438 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -244,17 +244,13 @@ struct hb_ot_face_cbdt_accelerator_t inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const { + unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ + if (cblc == NULL) { return false; // Not a color bitmap font. } - const OT::BitmapSizeTable* sizeTable = this->cblc->find_table(glyph); - if (sizeTable == NULL) { - return false; - } - - const OT::IndexSubtableArray& subtables = this->cblc + sizeTable->indexSubtableArrayOffset; - const OT::IndexSubtableRecord *subtable_record = subtables.find_table (glyph, sizeTable->numberOfIndexSubtables); + const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); if (subtable_record == NULL) { return false; } @@ -286,10 +282,10 @@ struct hb_ot_face_cbdt_accelerator_t } /* Convert to the font units. */ - extents->x_bearing *= upem / (float)(sizeTable->ppemX); - extents->y_bearing *= upem / (float)(sizeTable->ppemY); - extents->width *= upem / (float)(sizeTable->ppemX); - extents->height *= upem / (float)(sizeTable->ppemY); + extents->x_bearing *= upem / (float) x_ppem; + extents->y_bearing *= upem / (float) y_ppem; + extents->width *= upem / (float) x_ppem; + extents->height *= upem / (float) y_ppem; return true; } From a141d1da9bb0f91521a9a7749f9533c75cfe6a2f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 19:26:54 -0800 Subject: [PATCH 0109/1326] [CBDT] Implement IndexSubtableFormat3 --- src/hb-ot-cbdt-table.hh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 4770cf3f1..3bf579480 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -100,7 +100,8 @@ struct IndexSubtableHeader DEFINE_SIZE_STATIC(8); }; -struct IndexSubtableFormat1 +template +struct IndexSubtableFormat1Or3 { inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const { @@ -122,11 +123,14 @@ struct IndexSubtableFormat1 } IndexSubtableHeader header; - Offset offsetArrayZ[VAR]; + Offset offsetArrayZ[VAR]; DEFINE_SIZE_ARRAY(8, offsetArrayZ); }; +struct IndexSubtableFormat1 : IndexSubtableFormat1Or3 {}; +struct IndexSubtableFormat3 : IndexSubtableFormat1Or3 {}; + struct IndexSubtable { inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const @@ -135,6 +139,7 @@ struct IndexSubtable if (!u.header.sanitize (c)) return_trace (false); switch (u.header.indexFormat) { case 1: return_trace (u.format1.sanitize (c, glyph_count)); + case 3: return_trace (u.format3.sanitize (c, glyph_count)); default:return_trace (true); } } @@ -156,6 +161,7 @@ struct IndexSubtable *format = u.header.imageFormat; switch (u.header.indexFormat) { case 1: return u.format1.get_image_data (idx, offset, length); + case 3: return u.format3.get_image_data (idx, offset, length); default: return false; } } @@ -164,6 +170,7 @@ struct IndexSubtable union { IndexSubtableHeader header; IndexSubtableFormat1 format1; + IndexSubtableFormat3 format3; } u; public: DEFINE_SIZE_UNION (8, header); From b7068af423dba30fd831041aabf4b805d26fe349 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 19:36:30 -0800 Subject: [PATCH 0110/1326] [CBDT] Fix thinko! --- src/hb-ot-cbdt-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 3bf579480..7269688ee 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -216,7 +216,7 @@ struct IndexSubtableArray inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, sizeof (count)))) + if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count))) return_trace (false); for (unsigned int i = 0; i < count; i++) if (unlikely (!indexSubtablesZ[i].sanitize (c, this))) From e4bfccfb2a0f425ff69b0a50ca8a4731c4001069 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 19:43:33 -0800 Subject: [PATCH 0111/1326] [CBDT] Minor --- src/hb-ot-cbdt-table.hh | 21 ++++++++++++++------- src/hb-ot-font.cc | 38 ++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 7269688ee..52897abd3 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -56,6 +56,15 @@ struct SmallGlyphMetrics DEFINE_SIZE_STATIC(5); }; +struct BigGlyphMetrics : SmallGlyphMetrics +{ + CHAR vertBearingX; + CHAR vertBearingY; + BYTE vertAdvance; + + DEFINE_SIZE_STATIC(8); +}; + struct SBitLineMetrics { inline bool sanitize (hb_sanitize_context_t *c) const @@ -171,6 +180,7 @@ struct IndexSubtable IndexSubtableHeader header; IndexSubtableFormat1 format1; IndexSubtableFormat3 format3; + /* TODO: Format 2, 4, 5. */ } u; public: DEFINE_SIZE_UNION (8, header); @@ -321,7 +331,6 @@ struct CBLC { /* TODO: Make it possible to select strike. */ - const BitmapSizeTable *sizeTable = &Null(BitmapSizeTable); unsigned int count = sizeTables.len; for (uint32_t i = 0; i < count; ++i) { @@ -329,15 +338,13 @@ struct CBLC unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex; if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) { - sizeTable = &sizeTables[i]; - break; + *x_ppem = sizeTables[i].ppemX; + *y_ppem = sizeTables[i].ppemY; + return sizeTables[i].find_table (glyph, this); } } - *x_ppem = sizeTable->ppemX; - *y_ppem = sizeTable->ppemY; - - return sizeTable->find_table (glyph, this); + return NULL; } protected: diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 1b6cea438..df01bc9fa 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -246,14 +246,12 @@ struct hb_ot_face_cbdt_accelerator_t { unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ - if (cblc == NULL) { + if (cblc == NULL) return false; // Not a color bitmap font. - } const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); - if (subtable_record == NULL) { + if (subtable_record == NULL) return false; - } if (subtable_record->get_extents (extents)) return true; @@ -262,23 +260,27 @@ struct hb_ot_face_cbdt_accelerator_t if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) return false; - if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) - return false; - - switch (image_format) { - case 17: { - if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size)) - return false; + /* TODO Move the following into CBDT struct when adding more formats. */ - const OT::GlyphBitmapDataFormat17& glyphFormat17 = - OT::StructAtOffset (this->cbdt, image_offset); - glyphFormat17.glyphMetrics.get_extents (extents); - } - break; - default: - // TODO: Support other image formats. + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) return false; + + switch (image_format) + { + case 17: { + if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size)) + return false; + + const OT::GlyphBitmapDataFormat17& glyphFormat17 = + OT::StructAtOffset (this->cbdt, image_offset); + glyphFormat17.glyphMetrics.get_extents (extents); + } + break; + default: + // TODO: Support other image formats. + return false; + } } /* Convert to the font units. */ From 9f6144cdb9dd2bc8cd147306e678d76ae82663d8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 19:55:17 -0800 Subject: [PATCH 0112/1326] [CBDT] Add test for fetching glyph extents --- test/shaping/Makefile.am | 1 + .../ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf | Bin 0 -> 3724 bytes test/shaping/tests/color-fonts.tests | 1 + 3 files changed, 2 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf create mode 100644 test/shaping/tests/color-fonts.tests diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index c5efe6251..57369fd5b 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -44,6 +44,7 @@ TESTS = \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ tests/cluster.tests \ + tests/color-fonts.tests \ tests/context-matching.tests \ tests/cursive-positioning.tests \ tests/default-ignorables.tests \ diff --git a/test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf b/test/shaping/fonts/sha1sum/ee39587d13b2afa5499cc79e45780aa79293bbd4.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fa2d0e1367cfe81695bb37e1389085f4bda4b8e6 GIT binary patch literal 3724 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] From 8c842e4a44908cce0f416481c73dc0866a0a9c95 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 4 Dec 2016 20:28:38 -0800 Subject: [PATCH 0113/1326] [hb-fuzzer] Get glyph extents for output glyphs To exercise glyph-extents codepaths (glyf / CBLC+CBDT). --- test/fuzzing/hb-fuzzer.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/fuzzing/hb-fuzzer.cc b/test/fuzzing/hb-fuzzer.cc index b319a715a..c9f15d831 100644 --- a/test/fuzzing/hb-fuzzer.cc +++ b/test/fuzzing/hb-fuzzer.cc @@ -28,6 +28,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_buffer_add_utf32(buffer, text32, sizeof(text32)/sizeof(text32[0]), 0, -1); hb_buffer_guess_segment_properties(buffer); hb_shape(font, buffer, NULL, 0); + + unsigned int len = hb_buffer_get_length (buffer); + hb_glyph_info_t *infos = hb_buffer_get_glyph_infos (buffer, NULL); + //hb_glyph_position_t *positions = hb_buffer_get_glyph_positions (buffer, NULL); + for (unsigned int i = 0; i < len; i++) + { + hb_glyph_info_t info = infos[i]; + //hb_glyph_position_t pos = positions[i]; + + hb_glyph_extents_t extents; + hb_font_get_glyph_extents (font, info.codepoint, &extents); + } + hb_buffer_destroy(buffer); } From b843c6d8b66c2833cd35407ee494546465e6d775 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 5 Dec 2016 13:42:28 -0800 Subject: [PATCH 0114/1326] 1.3.4 --- NEWS | 8 ++++++++ configure.ac | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e83f25f2b..fb84c888a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +Overview of changes leading to 1.3.4 +Monday, December 5, 2016 +==================================== + +- Fix vertical glyph origin in hb-ot-font. +- Implement CBDT/CBLC color font glyph extents in hb-ot-font. + + Overview of changes leading to 1.3.3 Wednesday, September 28, 2016 ==================================== diff --git a/configure.ac b/configure.ac index b38ba98c7..0fdaf531e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.3.3], + [1.3.4], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 6d9d3c55bbd4209ba339ccd2b925bb4a6c97f622 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 1 Mar 2016 19:12:08 +0900 Subject: [PATCH 0115/1326] [GX] Add data types for encoding numerical variations --- src/hb-font-private.hh | 10 +++ src/hb-font.cc | 3 + src/hb-ot-layout-common-private.hh | 113 +++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index cda97a68c..3a1e31f06 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -108,6 +108,10 @@ struct hb_font_t { unsigned int x_ppem; unsigned int y_ppem; + /* Font variation coordinates. */ + int *coords; + unsigned int coord_count; + hb_font_funcs_t *klass; void *user_data; hb_destroy_func_t destroy; @@ -120,6 +124,8 @@ struct hb_font_t { { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } + inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } + inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) { return em_scale (v, dir_scale (direction)); } @@ -531,6 +537,10 @@ struct hb_font_t { scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ return (hb_position_t) (scaled / upem); } + inline hb_position_t em_scalef (float v, int scale) + { + return (hb_position_t) (v * scale / face->get_upem ()); + } }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/src/hb-font.cc b/src/hb-font.cc index 08fcd6475..b4b4d0a52 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1194,6 +1194,9 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ + NULL, /* coords */ + 0, /* coord_count */ + const_cast (&_hb_font_funcs_nil), /* klass */ NULL, /* user_data */ NULL, /* destroy */ diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 34fa1b773..a18ce74dc 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1236,6 +1236,119 @@ struct Device }; +struct VariationAxis +{ + inline float evaluate (int *coords, unsigned int coord_len) const + { + unsigned int i = axisIndex; + int coord = i < coord_len ? coords[i] : 0; + + int start = startCoord, peak = peakCoord, end = endCoord; + if (coord < start || coord > end) return 0.; + if (coord == peak) return 1.; + /* Interpolate */ + if (coord < peak) + return float (coord - start) / (peak - start); + else + return float (end - coord) / (end - peak); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Index axisIndex; + F2DOT14 startCoord; + F2DOT14 peakCoord; + F2DOT14 endCoord; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct VariationTuple +{ + inline float evaluate (int *coords, unsigned int coord_len) const + { + float v = 1.; + unsigned int count = axes.len; + for (unsigned int i = 0; i < count; i++) + v *= (this+axes[i]).evaluate (coords, coord_len); + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (axes.sanitize (c, this)); + } + + OffsetArrayOf + axes; + public: + DEFINE_SIZE_ARRAY (2, axes); +}; + +struct VariationMap +{ + inline const VariationTuple& operator [] (unsigned int i) const + { return this+tuples[i]; } + + inline unsigned int get_len (void) const + { return tuples.len; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (tuples.sanitize (c, this)); + } + + OffsetArrayOf + tuples; + public: + DEFINE_SIZE_ARRAY (2, tuples); +}; + +struct VariationDevice +{ + + inline hb_position_t get_x_delta (hb_font_t *font) const + { return font->em_scalef_x (get_delta (font->coords, font->coord_count)); } + + inline hb_position_t get_y_delta (hb_font_t *font) const + { return font->em_scalef_y (get_delta (font->coords, font->coord_count)); } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && c->check_range (&deltaValue, numDeltas * SHORT::static_size)); + } + + private: + + inline float get_delta (int *coords, unsigned int coord_count) const + { + float v = 0; + const VariationMap &map = this+variationMap; + unsigned int count = MIN ((unsigned int) numDeltas, map.get_len ()); + for (unsigned int i = 0; i < count; i++) + v += deltaValue[i] * map[i].evaluate (coords, coord_count); + return v; + } + + protected: + OffsetTo + variationMap; /* Offset to variation mapping for this table. */ + USHORT numDeltas; /* Number of deltas for in this table. */ + USHORT deltaFormat; /* Format identifier for this table: 0x10 */ + SHORT deltaValue[VAR]; /* Deltas as signed values in design space. */ + public: + DEFINE_SIZE_ARRAY (6, deltaValue); +}; + + } /* namespace OT */ From ca286703164caf1eda665f6f27ef83bf04e2f8ba Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 1 Mar 2016 19:29:36 +0900 Subject: [PATCH 0116/1326] [GX] Towards anisotropic interpolation Also hookup to ValueRecord and Anchors. --- src/hb-font-private.hh | 5 +++-- src/hb-font.cc | 9 +++++++-- src/hb-ot-layout-common-private.hh | 4 ++-- src/hb-ot-layout-gpos-table.hh | 20 ++++++++++---------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 3a1e31f06..48dc72564 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -109,8 +109,9 @@ struct hb_font_t { unsigned int y_ppem; /* Font variation coordinates. */ - int *coords; - unsigned int coord_count; + unsigned int num_coords; + int *x_coords; + int *y_coords; hb_font_funcs_t *klass; void *user_data; diff --git a/src/hb-font.cc b/src/hb-font.cc index b4b4d0a52..75c8515e5 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1165,6 +1165,8 @@ hb_font_create_sub_font (hb_font_t *parent) font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; + /* TODO: copy variation coordinates. */ + return font; } @@ -1194,8 +1196,9 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ - NULL, /* coords */ - 0, /* coord_count */ + 0, /* num_coords */ + NULL, /* x_coords */ + NULL, /* y_coords */ const_cast (&_hb_font_funcs_nil), /* klass */ NULL, /* user_data */ @@ -1251,6 +1254,8 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); + /* TODO: destroy variation coordinates. */ + free (font); } diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index a18ce74dc..cd26db338 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1315,10 +1315,10 @@ struct VariationDevice { inline hb_position_t get_x_delta (hb_font_t *font) const - { return font->em_scalef_x (get_delta (font->coords, font->coord_count)); } + { return font->em_scalef_x (get_delta (font->x_coords, font->num_coords)); } inline hb_position_t get_y_delta (hb_font_t *font) const - { return font->em_scalef_y (get_delta (font->coords, font->coord_count)); } + { return font->em_scalef_y (get_delta (font->y_coords, font->num_coords)); } inline bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index bbe390cf7..424a34e40 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -109,7 +109,6 @@ struct ValueFormat : USHORT const Value *values, hb_glyph_position_t &glyph_pos) const { - unsigned int x_ppem, y_ppem; unsigned int format = *this; hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); @@ -129,27 +128,28 @@ struct ValueFormat : USHORT if (!has_device ()) return; - x_ppem = font->x_ppem; - y_ppem = font->y_ppem; + bool use_x_device = font->x_ppem || font->num_coords; + bool use_y_device = font->y_ppem || font->num_coords; - if (!x_ppem && !y_ppem) return; + + if (!use_x_device && !use_y_device) return; /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (x_ppem) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); values++; } if (format & yPlaDevice) { - if (y_ppem) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); values++; } if (format & xAdvDevice) { - if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); values++; } } @@ -291,9 +291,9 @@ struct AnchorFormat3 *x = font->em_scale_x (xCoordinate); *y = font->em_scale_y (yCoordinate); - if (font->x_ppem) + if (font->x_ppem || font->num_coords) *x += (this+xDeviceTable).get_x_delta (font); - if (font->y_ppem) + if (font->y_ppem || font->num_coords) *y += (this+yDeviceTable).get_x_delta (font); } From a0c2366075fcb894212b9bf137e4dd34bb65537c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 1 Mar 2016 19:42:24 +0900 Subject: [PATCH 0117/1326] [GX] Break out early if factor is zero Also disable sanity-checking of variation records. --- src/hb-ot-layout-common-private.hh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index cd26db338..168dbe4c6 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1244,6 +1244,8 @@ struct VariationAxis int coord = i < coord_len ? coords[i] : 0; int start = startCoord, peak = peakCoord, end = endCoord; + //if (coord == 0) return 0; + //if (start < 0 && end > 0) return 0.; if (coord < start || coord > end) return 0.; if (coord == peak) return 1.; /* Interpolate */ @@ -1275,7 +1277,12 @@ struct VariationTuple float v = 1.; unsigned int count = axes.len; for (unsigned int i = 0; i < count; i++) - v *= (this+axes[i]).evaluate (coords, coord_len); + { + float factor = (this+axes[i]).evaluate (coords, coord_len); + v *= factor; + if (factor == 0.) + break; + } return v; } From 4c535a822f16b23a4e41e14d1b17fe179b83eabc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 2 Mar 2016 12:21:36 +0900 Subject: [PATCH 0118/1326] [GX] Hookup VariationDevice to Device table implementation --- src/hb-ot-layout-common-private.hh | 65 +++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 168dbe4c6..e34acd9f8 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1165,8 +1165,11 @@ struct ClassDef * Device Tables */ -struct Device +struct HintingDevice { + friend struct Device; + + private: inline hb_position_t get_x_delta (hb_font_t *font) const { return get_delta (font->x_ppem, font->x_scale); } @@ -1320,6 +1323,9 @@ struct VariationMap struct VariationDevice { + friend struct Device; + + private: inline hb_position_t get_x_delta (hb_font_t *font) const { return font->em_scalef_x (get_delta (font->x_coords, font->num_coords)); } @@ -1355,6 +1361,63 @@ struct VariationDevice DEFINE_SIZE_ARRAY (6, deltaValue); }; +struct Device +{ + inline hb_position_t get_x_delta (hb_font_t *font) const + { + switch (u.b.format) + { + case 1: case 2: case 3: + return u.hinting.get_x_delta (font); + case 0x10: + return u.variation.get_x_delta (font); + default: + return 0; + } + } + inline hb_position_t get_y_delta (hb_font_t *font) const + { + switch (u.b.format) + { + case 1: case 2: case 3: + return u.hinting.get_x_delta (font); + case 0x10: + return u.variation.get_x_delta (font); + default: + return 0; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.b.format.sanitize (c)) return_trace (false); + switch (u.b.format) { + case 1: case 2: case 3: + return_trace (u.hinting.sanitize (c)); + case 0x10: + return_trace (u.variation.sanitize (c)); + default: + return_trace (true); + } + } + + protected: + union { + struct { + USHORT reserved1; + USHORT reserved2; + USHORT format; /* Format identifier */ + public: + DEFINE_SIZE_STATIC (6); + } b; + HintingDevice hinting; + VariationDevice variation; + } u; + public: + DEFINE_SIZE_UNION (6, b); +}; + } /* namespace OT */ From 15c5ee67473a17859a919104c5e6fed1f813aa65 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 2 Mar 2016 12:41:49 +0900 Subject: [PATCH 0119/1326] [GX] Minor rename --- src/hb-ot-layout-common-private.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index e34acd9f8..b1dcb01ce 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1336,7 +1336,7 @@ struct VariationDevice inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_range (&deltaValue, numDeltas * SHORT::static_size)); + return_trace (c->check_struct (this) && c->check_range (&deltaValue, deltaCount * SHORT::static_size)); } private: @@ -1345,7 +1345,7 @@ struct VariationDevice { float v = 0; const VariationMap &map = this+variationMap; - unsigned int count = MIN ((unsigned int) numDeltas, map.get_len ()); + unsigned int count = MIN ((unsigned int) deltaCount, map.get_len ()); for (unsigned int i = 0; i < count; i++) v += deltaValue[i] * map[i].evaluate (coords, coord_count); return v; @@ -1354,7 +1354,7 @@ struct VariationDevice protected: OffsetTo variationMap; /* Offset to variation mapping for this table. */ - USHORT numDeltas; /* Number of deltas for in this table. */ + USHORT deltaCount; /* Number of deltas in this table. */ USHORT deltaFormat; /* Format identifier for this table: 0x10 */ SHORT deltaValue[VAR]; /* Deltas as signed values in design space. */ public: From ed8a9067ca0fe51ac4b80dab55db596763df72bb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 2 Mar 2016 12:54:35 -0800 Subject: [PATCH 0120/1326] [GX] Minor --- src/hb-ot-layout-common-private.hh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index b1dcb01ce..52d213cd4 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1336,7 +1336,8 @@ struct VariationDevice inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_range (&deltaValue, deltaCount * SHORT::static_size)); + return_trace (c->check_struct (this) && + c->check_array (&deltaValue, SHORT::static_size, deltaCount)); } private: From 976eeb8e025e2b7601a91e661d6e9a88bf8afbd2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 12 Mar 2016 23:28:12 -0800 Subject: [PATCH 0121/1326] [GX] Minor --- src/hb-ot-layout-common-private.hh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 52d213cd4..3154cfe7a 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1243,8 +1243,7 @@ struct VariationAxis { inline float evaluate (int *coords, unsigned int coord_len) const { - unsigned int i = axisIndex; - int coord = i < coord_len ? coords[i] : 0; + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; int start = startCoord, peak = peakCoord, end = endCoord; //if (coord == 0) return 0; From 71b06fd392680b6fcfece60d8a83ba6c56eada09 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 12 Mar 2016 23:49:09 -0800 Subject: [PATCH 0122/1326] [GX] Add VariationAlternates, to allow conditional lookups in GSUB/GPOS Not hooked up to runtime yet. --- src/hb-open-type-private.hh | 1 + src/hb-ot-layout-common-private.hh | 99 +++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 66f1c08df..865429da2 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -630,6 +630,7 @@ struct IntType inline operator Type(void) const { return v; } inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } + inline unsigned int get_size (void) const { return Size; } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } inline int cmp (Type a) const { diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 3154cfe7a..328472fb1 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -575,6 +575,7 @@ struct LookupFlag : USHORT IgnoreMarks = 0x0008u, IgnoreFlags = 0x000Eu, UseMarkFilteringSet = 0x0010u, + UseVariationAlternates= 0x0020u, Reserved = 0x00E0u, MarkAttachmentType = 0xFF00u }; @@ -587,6 +588,88 @@ struct LookupFlag : USHORT HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags); namespace OT { +struct VariationGridAxis +{ + inline int locate (int *coords, unsigned int coord_len) const + { + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; + + unsigned int count = axisCoords.len; + unsigned int i = 0; + while (i + 1 < count && coord < axisCoords[i + 1]) + i++; + + return axisCoords[i] <= coord ? i : -1; + } + + inline unsigned int get_len (void) const + { + return axisCoords.len - 1; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && axisCoords.sanitize (c)); + } + + Index axisIndex; + SortedArrayOf axisCoords; + public: + DEFINE_SIZE_ARRAY (4, axisCoords); +}; + +struct VariationGrid +{ + inline int locate (int *coords, unsigned int coord_len) const + { + int location = 0; + unsigned int count = axes.len; + for (unsigned int i = 0; i < count; i++) + { + const VariationGridAxis &axis = (this+axes[i]); + int axisLoc = axis.locate (coords, coord_len); + if (axisLoc == -1) + return -1; + location = location * (axis.get_len () - 1) + axisLoc; /* XXX Check for overflow?. */ + } + return location; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (axes.sanitize (c, this)); + } + + OffsetArrayOf + axes; + public: + DEFINE_SIZE_ARRAY (2, axes); +}; + +struct VariationAlternates +{ + inline unsigned int get_lookup_index (int *coords, unsigned int coord_len) const + { + int location = (this+grid).locate (coords, coord_len); + if (location == -1) + return 0xFFFE; /* TODO: give it a name. */ + return lookupIndex[location]; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (grid.sanitize (c, this) && lookupIndex.sanitize (c)); + } + + OffsetTo grid; + IndexArray lookupIndex; + public: + DEFINE_SIZE_ARRAY (4, lookupIndex); +}; + struct Lookup { inline unsigned int get_subtable_count (void) const { return subTable.len; } @@ -655,10 +738,17 @@ struct Lookup TRACE_SANITIZE (this); /* Real sanitize of the subtables is done by GSUB/GPOS/... */ if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false); + const void *cursor = &StructAfter (subTable); if (lookupFlag & LookupFlag::UseMarkFilteringSet) { - const USHORT &markFilteringSet = StructAfter (subTable); + const USHORT &markFilteringSet = CastR (cursor); if (!markFilteringSet.sanitize (c)) return_trace (false); + cursor = &StructAfter (markFilteringSet); + } + if (lookupFlag & LookupFlag::UseVariationAlternates) + { + const OffsetTo &varAlts = CastR > (cursor); + if (!varAlts.sanitize (c, this)) return_trace (false); } return_trace (true); } @@ -671,8 +761,13 @@ struct Lookup USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets * structure. This field is only present if bit * UseMarkFilteringSet of lookup flags is set. */ + OffsetTo + variationAlternatesZ[VAR]; + /* Index (base 0) into GDEF mark glyph sets + * structure. This field is only present if bit + * UseMarkFilteringSet of lookup flags is set. */ public: - DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX); + DEFINE_SIZE_MIN (6); }; typedef OffsetListOf LookupList; From baa329c6a12c7ffd56feed32351d9405b7d1651b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 18 Mar 2016 15:52:24 -0700 Subject: [PATCH 0123/1326] [GX] Add compact VariationDevice implementation Add compact format that uses signed bytes instead of shorts. --- src/hb-open-type-private.hh | 1 + src/hb-ot-layout-common-private.hh | 35 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 865429da2..9bd2fa417 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -653,6 +653,7 @@ struct IntType typedef IntType CHAR; /* 8-bit signed integer. */ typedef IntType BYTE; /* 8-bit unsigned integer. */ +typedef IntType INT8; /* 8-bit signed integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType ULONG; /* 32-bit unsigned integer. */ diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 328472fb1..61bf1faa7 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1419,6 +1419,9 @@ struct VariationDevice { friend struct Device; + static const unsigned short FORMAT_BYTES = 0x0100; + static const unsigned short FORMAT_SHORTS = 0x0101; + private: inline hb_position_t get_x_delta (hb_font_t *font) const @@ -1431,29 +1434,39 @@ struct VariationDevice { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (&deltaValue, SHORT::static_size, deltaCount)); + c->check_array (&deltaValue, get_item_size (), deltaCount)); } private: + inline unsigned int get_item_size (void) const + { return deltaFormat == FORMAT_BYTES ? 1 : 2; } + inline float get_delta (int *coords, unsigned int coord_count) const { float v = 0; const VariationMap &map = this+variationMap; unsigned int count = MIN ((unsigned int) deltaCount, map.get_len ()); - for (unsigned int i = 0; i < count; i++) - v += deltaValue[i] * map[i].evaluate (coords, coord_count); + if (get_item_size () == 1) + for (unsigned int i = 0; i < count; i++) + v += deltaValue.bytesZ[i] * map[i].evaluate (coords, coord_count); + else + for (unsigned int i = 0; i < count; i++) + v += deltaValue.shortsZ[i] * map[i].evaluate (coords, coord_count); return v; } protected: OffsetTo - variationMap; /* Offset to variation mapping for this table. */ - USHORT deltaCount; /* Number of deltas in this table. */ - USHORT deltaFormat; /* Format identifier for this table: 0x10 */ - SHORT deltaValue[VAR]; /* Deltas as signed values in design space. */ + variationMap; /* Offset to variation mapping for this table. */ + USHORT deltaCount; /* Number of deltas in this table. */ + USHORT deltaFormat; /* Format identifier for this table: 0x0100 or 0x0101 */ + union { + INT8 bytesZ[VAR]; /* Deltas as signed bytes in design space; format=0x0100 */ + SHORT shortsZ[VAR]; /* Deltas as signed shorts in design space; format=0x0101 */ + } deltaValue; public: - DEFINE_SIZE_ARRAY (6, deltaValue); + DEFINE_SIZE_ARRAY (6, deltaValue.shortsZ); }; struct Device @@ -1464,7 +1477,7 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_x_delta (font); - case 0x10: + case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: return u.variation.get_x_delta (font); default: return 0; @@ -1476,7 +1489,7 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_x_delta (font); - case 0x10: + case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: return u.variation.get_x_delta (font); default: return 0; @@ -1490,7 +1503,7 @@ struct Device switch (u.b.format) { case 1: case 2: case 3: return_trace (u.hinting.sanitize (c)); - case 0x10: + case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: return_trace (u.variation.sanitize (c)); default: return_trace (true); From bb4d2e6ed562c248fff15313a013d49e38a18789 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 13:08:52 -0700 Subject: [PATCH 0124/1326] [GX] Free GX coordinates --- src/hb-font.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 75c8515e5..978e7dd06 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1254,7 +1254,10 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - /* TODO: destroy variation coordinates. */ + if (font->x_coords) + free (font->x_coords); + if (font->y_coords && font->y_coords != font->x_coords) + free (font->y_coords); free (font); } From 8dddc231cf9d934eb93a39f2657717cbdad43a64 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 13:17:33 -0700 Subject: [PATCH 0125/1326] [GX] Revert "[GX] Add VariationAlternates, to allow conditional lookups in GSUB/GPOS" This reverts commit 2859f1c7174d6f7ae5dcf0db5411bc0182b21594. We are going in a different direction. --- src/hb-open-type-private.hh | 1 - src/hb-ot-layout-common-private.hh | 99 +----------------------------- 2 files changed, 2 insertions(+), 98 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 9bd2fa417..bc7e9a48e 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -630,7 +630,6 @@ struct IntType inline operator Type(void) const { return v; } inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } - inline unsigned int get_size (void) const { return Size; } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } inline int cmp (Type a) const { diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 61bf1faa7..bef26e11f 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -575,7 +575,6 @@ struct LookupFlag : USHORT IgnoreMarks = 0x0008u, IgnoreFlags = 0x000Eu, UseMarkFilteringSet = 0x0010u, - UseVariationAlternates= 0x0020u, Reserved = 0x00E0u, MarkAttachmentType = 0xFF00u }; @@ -588,88 +587,6 @@ struct LookupFlag : USHORT HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags); namespace OT { -struct VariationGridAxis -{ - inline int locate (int *coords, unsigned int coord_len) const - { - int coord = axisIndex < coord_len ? coords[axisIndex] : 0; - - unsigned int count = axisCoords.len; - unsigned int i = 0; - while (i + 1 < count && coord < axisCoords[i + 1]) - i++; - - return axisCoords[i] <= coord ? i : -1; - } - - inline unsigned int get_len (void) const - { - return axisCoords.len - 1; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && axisCoords.sanitize (c)); - } - - Index axisIndex; - SortedArrayOf axisCoords; - public: - DEFINE_SIZE_ARRAY (4, axisCoords); -}; - -struct VariationGrid -{ - inline int locate (int *coords, unsigned int coord_len) const - { - int location = 0; - unsigned int count = axes.len; - for (unsigned int i = 0; i < count; i++) - { - const VariationGridAxis &axis = (this+axes[i]); - int axisLoc = axis.locate (coords, coord_len); - if (axisLoc == -1) - return -1; - location = location * (axis.get_len () - 1) + axisLoc; /* XXX Check for overflow?. */ - } - return location; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (axes.sanitize (c, this)); - } - - OffsetArrayOf - axes; - public: - DEFINE_SIZE_ARRAY (2, axes); -}; - -struct VariationAlternates -{ - inline unsigned int get_lookup_index (int *coords, unsigned int coord_len) const - { - int location = (this+grid).locate (coords, coord_len); - if (location == -1) - return 0xFFFE; /* TODO: give it a name. */ - return lookupIndex[location]; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (grid.sanitize (c, this) && lookupIndex.sanitize (c)); - } - - OffsetTo grid; - IndexArray lookupIndex; - public: - DEFINE_SIZE_ARRAY (4, lookupIndex); -}; - struct Lookup { inline unsigned int get_subtable_count (void) const { return subTable.len; } @@ -738,17 +655,10 @@ struct Lookup TRACE_SANITIZE (this); /* Real sanitize of the subtables is done by GSUB/GPOS/... */ if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false); - const void *cursor = &StructAfter (subTable); if (lookupFlag & LookupFlag::UseMarkFilteringSet) { - const USHORT &markFilteringSet = CastR (cursor); + const USHORT &markFilteringSet = StructAfter (subTable); if (!markFilteringSet.sanitize (c)) return_trace (false); - cursor = &StructAfter (markFilteringSet); - } - if (lookupFlag & LookupFlag::UseVariationAlternates) - { - const OffsetTo &varAlts = CastR > (cursor); - if (!varAlts.sanitize (c, this)) return_trace (false); } return_trace (true); } @@ -761,13 +671,8 @@ struct Lookup USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets * structure. This field is only present if bit * UseMarkFilteringSet of lookup flags is set. */ - OffsetTo - variationAlternatesZ[VAR]; - /* Index (base 0) into GDEF mark glyph sets - * structure. This field is only present if bit - * UseMarkFilteringSet of lookup flags is set. */ public: - DEFINE_SIZE_MIN (6); + DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX); }; typedef OffsetListOf LookupList; From a7edeb6f02cbc4418285fdfc58ef8a8740a380e9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 15:39:52 -0700 Subject: [PATCH 0126/1326] Make OffsetArrayOf take OffsetType template argument --- src/hb-open-type-private.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index bc7e9a48e..5b7ff337e 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -952,8 +952,8 @@ struct ArrayOf }; /* Array of Offset's */ -template -struct OffsetArrayOf : ArrayOf > {}; +template +struct OffsetArrayOf : ArrayOf > {}; /* Array of offsets relative to the beginning of the array itself. */ template From dc9f2297998b4cbc4f9e4c2591fc2bb5f92986d1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 15:40:15 -0700 Subject: [PATCH 0127/1326] [GX] Port variation stuff to Variation Store design Not hooked up to GDEF yet. --- src/hb-ot-layout-common-private.hh | 294 ++++++++++++++++++----------- src/hb-ot-layout-gpos-table.hh | 2 +- 2 files changed, 184 insertions(+), 112 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index bef26e11f..ad67972e0 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1161,6 +1161,180 @@ struct ClassDef }; +/* + * Item Variation Store + */ + +struct VarRegionAxis +{ + inline float evaluate (int coord) const + { + int start = startCoord, peak = peakCoord, end = endCoord; + + /* TODO Move these to sanitize(). */ + if (unlikely (start > peak || peak > end)) + return 1.; + if (unlikely (start < 0 && end > 0 && peak != 0)) + return 1.; + + if (peak == 0 || coord == peak) + return 1.; + + if (coord <= start || end <= coord) + return 0.; + + /* Interpolate */ + if (coord < peak) + return float (coord - start) / (peak - start); + else + return float (end - coord) / (end - peak); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + /* TODO Handle invalid start/peak/end configs, so we don't + * have to do that at runtime. */ + } + + public: + F2DOT14 startCoord; + F2DOT14 peakCoord; + F2DOT14 endCoord; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct VarRegionList +{ + inline float evaluate (unsigned int region_index, + int *coords, unsigned int coord_len) const + { + if (unlikely (region_index >= regionCount)) + return 0.; + + const VarRegionAxis *axes = axesZ + (region_index * axisCount); + + float v = 1.; + unsigned int count = MIN (coord_len, (unsigned int) axisCount); + for (unsigned int i = 0; i < count; i++) + { + float factor = axes[i].evaluate (coords[i]); + if (factor == 0.) + return 0.; + v *= factor; + } + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (axesZ, axesZ[0].static_size, + (unsigned int) axisCount * (unsigned int) regionCount)); + } + + protected: + USHORT axisCount; + USHORT regionCount; + VarRegionAxis axesZ[VAR]; + public: + DEFINE_SIZE_ARRAY (4, axesZ); +}; + +struct VarData +{ + inline unsigned int get_row_size (void) const + { return shortCount + regionIndices.len; } + + inline unsigned int get_size (void) const + { return itemCount * get_row_size (); } + + inline float get_delta (unsigned int inner, + int *coords, unsigned int coord_count, + const VarRegionList ®ions) const + { + if (unlikely (inner >= itemCount)) + return 0.; + + unsigned int count = regionIndices.len; + unsigned int scount = shortCount; + + const BYTE *bytes = &StructAfter (regionIndices); + const BYTE *row = bytes + inner * (scount + count); + + + float delta = 0.; + unsigned int i = 0; + + const SHORT *scursor = reinterpret_cast (row); + for (; i < scount; i++) + { + float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); + delta += scalar * *scursor++; + } + const INT8 *bcursor = reinterpret_cast (scursor); + for (; i < count; i++) + { + float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); + delta += scalar * *bcursor++; + } + + return delta; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + regionIndices.sanitize(c) && + shortCount <= regionIndices.len && + c->check_array (&StructAfter (regionIndices), + get_row_size (), itemCount)); + } + + protected: + USHORT itemCount; + USHORT shortCount; + ArrayOf regionIndices; + BYTE bytesX[VAR]; + public: + DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX); +}; + +struct VarStore +{ + inline float get_delta (unsigned int outer, unsigned int inner, + int *coords, unsigned int coord_count) const + { + if (unlikely (outer >= dataSets.len)) + return 0.; + + return (this+dataSets[outer]).get_delta (inner, + coords, coord_count, + this+regions); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + format == 1 && + regions.sanitize (c, this) && + dataSets.sanitize (c, this)); + } + + protected: + USHORT format; + OffsetTo regions; + OffsetArrayOf dataSets; + public: + DEFINE_SIZE_ARRAY (8, dataSets); +}; + + /* * Device Tables */ @@ -1238,95 +1412,10 @@ struct HintingDevice DEFINE_SIZE_ARRAY (6, deltaValue); }; - -struct VariationAxis -{ - inline float evaluate (int *coords, unsigned int coord_len) const - { - int coord = axisIndex < coord_len ? coords[axisIndex] : 0; - - int start = startCoord, peak = peakCoord, end = endCoord; - //if (coord == 0) return 0; - //if (start < 0 && end > 0) return 0.; - if (coord < start || coord > end) return 0.; - if (coord == peak) return 1.; - /* Interpolate */ - if (coord < peak) - return float (coord - start) / (peak - start); - else - return float (end - coord) / (end - peak); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } - - public: - Index axisIndex; - F2DOT14 startCoord; - F2DOT14 peakCoord; - F2DOT14 endCoord; - public: - DEFINE_SIZE_STATIC (8); -}; - -struct VariationTuple -{ - inline float evaluate (int *coords, unsigned int coord_len) const - { - float v = 1.; - unsigned int count = axes.len; - for (unsigned int i = 0; i < count; i++) - { - float factor = (this+axes[i]).evaluate (coords, coord_len); - v *= factor; - if (factor == 0.) - break; - } - return v; - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (axes.sanitize (c, this)); - } - - OffsetArrayOf - axes; - public: - DEFINE_SIZE_ARRAY (2, axes); -}; - -struct VariationMap -{ - inline const VariationTuple& operator [] (unsigned int i) const - { return this+tuples[i]; } - - inline unsigned int get_len (void) const - { return tuples.len; } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (tuples.sanitize (c, this)); - } - - OffsetArrayOf - tuples; - public: - DEFINE_SIZE_ARRAY (2, tuples); -}; - struct VariationDevice { friend struct Device; - static const unsigned short FORMAT_BYTES = 0x0100; - static const unsigned short FORMAT_SHORTS = 0x0101; - private: inline hb_position_t get_x_delta (hb_font_t *font) const @@ -1338,40 +1427,24 @@ struct VariationDevice inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - c->check_array (&deltaValue, get_item_size (), deltaCount)); + return_trace (c->check_struct (this)); } private: - inline unsigned int get_item_size (void) const - { return deltaFormat == FORMAT_BYTES ? 1 : 2; } - inline float get_delta (int *coords, unsigned int coord_count) const { float v = 0; - const VariationMap &map = this+variationMap; - unsigned int count = MIN ((unsigned int) deltaCount, map.get_len ()); - if (get_item_size () == 1) - for (unsigned int i = 0; i < count; i++) - v += deltaValue.bytesZ[i] * map[i].evaluate (coords, coord_count); - else - for (unsigned int i = 0; i < count; i++) - v += deltaValue.shortsZ[i] * map[i].evaluate (coords, coord_count); + /* XXXXXXXXXXXXXXX call into GDEF. */ return v; } protected: - OffsetTo - variationMap; /* Offset to variation mapping for this table. */ - USHORT deltaCount; /* Number of deltas in this table. */ - USHORT deltaFormat; /* Format identifier for this table: 0x0100 or 0x0101 */ - union { - INT8 bytesZ[VAR]; /* Deltas as signed bytes in design space; format=0x0100 */ - SHORT shortsZ[VAR]; /* Deltas as signed shorts in design space; format=0x0101 */ - } deltaValue; + USHORT outerIndex; + USHORT innerIndex; + USHORT deltaFormat; /* Format identifier for this table: 0x0x8000 */ public: - DEFINE_SIZE_ARRAY (6, deltaValue.shortsZ); + DEFINE_SIZE_STATIC (6); }; struct Device @@ -1382,7 +1455,7 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_x_delta (font); - case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: + case 0x8000: return u.variation.get_x_delta (font); default: return 0; @@ -1394,8 +1467,7 @@ struct Device { case 1: case 2: case 3: return u.hinting.get_x_delta (font); - case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: - return u.variation.get_x_delta (font); + case 0x8000: default: return 0; } @@ -1408,7 +1480,7 @@ struct Device switch (u.b.format) { case 1: case 2: case 3: return_trace (u.hinting.sanitize (c)); - case VariationDevice::FORMAT_BYTES: case VariationDevice::FORMAT_SHORTS: + case 0x8000: return_trace (u.variation.sanitize (c)); default: return_trace (true); diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 424a34e40..d5db21d80 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -370,7 +370,7 @@ struct AnchorMatrix { TRACE_SANITIZE (this); if (!c->check_struct (this)) return_trace (false); - if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return_trace (false); + if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false); unsigned int count = rows * cols; if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false); for (unsigned int i = 0; i < count; i++) From 5c971f8dbc823dbad4a2869cf9e835095ab6ddb2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 16:05:17 -0700 Subject: [PATCH 0128/1326] Minor change to GDEF, in prep for new version --- src/hb-ot-layout-gdef-table.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 2b4bc5a02..93323c8d6 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -369,9 +369,9 @@ struct GDEF hb_position_t *caret_array /* OUT */) const { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); } - inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef[0] != 0; } + inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const - { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } + { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -382,7 +382,7 @@ struct GDEF attachList.sanitize (c, this) && ligCaretList.sanitize (c, this) && markAttachClassDef.sanitize (c, this) && - (version.to_int () < 0x00010002u || markGlyphSetsDef[0].sanitize (c, this))); + (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this))); } @@ -428,12 +428,12 @@ struct GDEF * mark attachment type--from beginning * of GDEF header (may be Null) */ OffsetTo - markGlyphSetsDef[VAR]; /* Offset to the table of mark set + markGlyphSetsDef; /* Offset to the table of mark set * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 00010002. */ public: - DEFINE_SIZE_ARRAY (12, markGlyphSetsDef); + DEFINE_SIZE_MIN (12); }; From f0c3fd8c9ab402be923fe0845fb51d99841829b6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 16:22:45 -0700 Subject: [PATCH 0129/1326] [GX] Add varStore member to GDEF Still not hooked up from GPOS. --- src/hb-ot-layout-gdef-table.hh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 93323c8d6..f8bbe3130 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -373,6 +373,11 @@ struct GDEF inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } + inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; } + inline float get_var_delta (unsigned int outer, unsigned int inner, + int *coords, unsigned int coord_count) const + { return version.to_int () >= 0x00010003u ? (this+varStore).get_delta (outer, inner, coords, coord_count) : 0.; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -382,7 +387,8 @@ struct GDEF attachList.sanitize (c, this) && ligCaretList.sanitize (c, this) && markAttachClassDef.sanitize (c, this) && - (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this))); + (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && + (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); } @@ -410,7 +416,7 @@ struct GDEF protected: FixedVersion<>version; /* Version of the GDEF table--currently - * 0x00010002u */ + * 0x00010003u */ OffsetTo glyphClassDef; /* Offset to class definition table * for glyph type--from beginning of @@ -431,7 +437,12 @@ struct GDEF markGlyphSetsDef; /* Offset to the table of mark set * definitions--from beginning of GDEF * header (may be NULL). Introduced - * in version 00010002. */ + * in version 0x00010002. */ + OffsetTo + varStore; /* Offset to the table of Item Variation + * Store--from beginning of GDEF + * header (may be NULL). Introduced + * in version 0x00010003. */ public: DEFINE_SIZE_MIN (12); }; From 49cb87850c2692be45b201168c8ce10b263168cc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 16:27:03 -0700 Subject: [PATCH 0130/1326] [GX] Pass apply-context down to get_anchor() Needed to access GDEF for varStore. --- src/hb-ot-layout-gpos-table.hh | 57 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index d5db21d80..83b806010 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -231,11 +231,12 @@ struct ValueFormat : USHORT struct AnchorFormat1 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -254,18 +255,19 @@ struct AnchorFormat1 struct AnchorFormat2 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { - unsigned int x_ppem = font->x_ppem; - unsigned int y_ppem = font->y_ppem; - hb_position_t cx, cy; - hb_bool_t ret; + hb_font_t *font = c->font; + unsigned int x_ppem = font->x_ppem; + unsigned int y_ppem = font->y_ppem; + hb_position_t cx, cy; + hb_bool_t ret; - ret = (x_ppem || y_ppem) && - font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); - *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); - *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); + ret = (x_ppem || y_ppem) && + font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); + *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate); + *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -285,16 +287,17 @@ struct AnchorFormat2 struct AnchorFormat3 { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, hb_position_t *x, hb_position_t *y) const { - *x = font->em_scale_x (xCoordinate); - *y = font->em_scale_y (yCoordinate); + hb_font_t *font = c->font; + *x = font->em_scale_x (xCoordinate); + *y = font->em_scale_y (yCoordinate); - if (font->x_ppem || font->num_coords) - *x += (this+xDeviceTable).get_x_delta (font); - if (font->y_ppem || font->num_coords) - *y += (this+yDeviceTable).get_x_delta (font); + if (font->x_ppem || font->num_coords) + *x += (this+xDeviceTable).get_x_delta (font); + if (font->y_ppem || font->num_coords) + *y += (this+yDeviceTable).get_x_delta (font); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -321,14 +324,14 @@ struct AnchorFormat3 struct Anchor { - inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id, + inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id, hb_position_t *x, hb_position_t *y) const { *x = *y = 0; switch (u.format) { - case 1: u.format1.get_anchor (font, glyph_id, x, y); return; - case 2: u.format2.get_anchor (font, glyph_id, x, y); return; - case 3: u.format3.get_anchor (font, glyph_id, x, y); return; + case 1: u.format1.get_anchor (c, glyph_id, x, y); return; + case 2: u.format2.get_anchor (c, glyph_id, x, y); return; + case 3: u.format3.get_anchor (c, glyph_id, x, y); return; default: return; } } @@ -428,8 +431,8 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; - mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y); - glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y); + mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); + glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); hb_glyph_position_t &o = buffer->cur_pos(); o.x_offset = base_x - mark_x; @@ -931,8 +934,8 @@ struct CursivePosFormat1 unsigned int j = skippy_iter.idx; hb_position_t entry_x, entry_y, exit_x, exit_y; - (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y); + (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); + (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); hb_glyph_position_t *pos = buffer->pos; From dcfd309533ac83e44369dea7204d668623b08207 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 16:51:07 -0700 Subject: [PATCH 0131/1326] [GX] Change GDEF API to return varStore --- src/hb-ot-layout-gdef-table.hh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index f8bbe3130..e7d14f660 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -374,9 +374,8 @@ struct GDEF { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; } - inline float get_var_delta (unsigned int outer, unsigned int inner, - int *coords, unsigned int coord_count) const - { return version.to_int () >= 0x00010003u ? (this+varStore).get_delta (outer, inner, coords, coord_count) : 0.; } + inline const VarStore &get_var_store (void) const + { return version.to_int () >= 0x00010003u ? this+varStore : Null(VarStore); } inline bool sanitize (hb_sanitize_context_t *c) const { From 151d93de8a595924a8dcb00fcba648b4b3df0bf5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 17:03:11 -0700 Subject: [PATCH 0132/1326] [GX] Hook up GPOS to Variation Store stored in GDEF Untested. --- src/hb-ot-layout-common-private.hh | 22 +++++++-------- src/hb-ot-layout-gdef-table.hh | 27 ++++++++++++------- src/hb-ot-layout-gpos-table.hh | 40 +++++++++++++--------------- src/hb-ot-layout-gsubgpos-private.hh | 2 ++ 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index ad67972e0..8c63ad983 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1418,11 +1418,11 @@ struct VariationDevice private: - inline hb_position_t get_x_delta (hb_font_t *font) const - { return font->em_scalef_x (get_delta (font->x_coords, font->num_coords)); } + inline hb_position_t get_x_delta (hb_font_t *font, const VarStore &store) const + { return font->em_scalef_x (get_delta (store, font->x_coords, font->num_coords)); } - inline hb_position_t get_y_delta (hb_font_t *font) const - { return font->em_scalef_y (get_delta (font->y_coords, font->num_coords)); } + inline hb_position_t get_y_delta (hb_font_t *font, const VarStore &store) const + { return font->em_scalef_y (get_delta (store, font->y_coords, font->num_coords)); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1432,11 +1432,10 @@ struct VariationDevice private: - inline float get_delta (int *coords, unsigned int coord_count) const + inline float get_delta (const VarStore &store, + int *coords, unsigned int coord_count) const { - float v = 0; - /* XXXXXXXXXXXXXXX call into GDEF. */ - return v; + return store.get_delta (outerIndex, innerIndex, coords, coord_count); } protected: @@ -1449,25 +1448,26 @@ struct VariationDevice struct Device { - inline hb_position_t get_x_delta (hb_font_t *font) const + inline hb_position_t get_x_delta (hb_font_t *font, const VarStore &store) const { switch (u.b.format) { case 1: case 2: case 3: return u.hinting.get_x_delta (font); case 0x8000: - return u.variation.get_x_delta (font); + return u.variation.get_x_delta (font, store); default: return 0; } } - inline hb_position_t get_y_delta (hb_font_t *font) const + inline hb_position_t get_y_delta (hb_font_t *font, const VarStore &store) const { switch (u.b.format) { case 1: case 2: case 3: return u.hinting.get_x_delta (font); case 0x8000: + return u.variation.get_y_delta (font, store); default: return 0; } diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index e7d14f660..2a92ece49 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -97,7 +97,7 @@ struct CaretValueFormat1 friend struct CaretValue; private: - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const + inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); } @@ -146,11 +146,11 @@ struct CaretValueFormat3 { friend struct CaretValue; - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const + inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VarStore &var_store) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? - font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) : - font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); + font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : + font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -172,12 +172,15 @@ struct CaretValueFormat3 struct CaretValue { - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const + inline hb_position_t get_caret_value (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph_id, + const VarStore &var_store) const { switch (u.format) { - case 1: return u.format1.get_caret_value (font, direction, glyph_id); + case 1: return u.format1.get_caret_value (font, direction); case 2: return u.format2.get_caret_value (font, direction, glyph_id); - case 3: return u.format3.get_caret_value (font, direction, glyph_id); + case 3: return u.format3.get_caret_value (font, direction, var_store); default:return 0; } } @@ -210,6 +213,7 @@ struct LigGlyph inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, + const VarStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -218,7 +222,7 @@ struct LigGlyph const OffsetTo *array = carets.sub_array (start_offset, caret_count); unsigned int count = *caret_count; for (unsigned int i = 0; i < count; i++) - caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id); + caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store); } return carets.len; @@ -244,6 +248,7 @@ struct LigCaretList inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, + const VarStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -256,7 +261,7 @@ struct LigCaretList return 0; } const LigGlyph &lig_glyph = this+ligGlyph[index]; - return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); + return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -367,7 +372,9 @@ struct GDEF unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const - { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); } + { return (this+ligCaretList).get_lig_carets (font, + direction, glyph_id, get_var_store(), + start_offset, caret_count, caret_array); } inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 83b806010..1893f0e4e 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -103,17 +103,17 @@ struct ValueFormat : USHORT inline unsigned int get_size (void) const { return get_len () * Value::static_size; } - void apply_value (hb_font_t *font, - hb_direction_t direction, + void apply_value (hb_apply_context_t *c, const void *base, const Value *values, hb_glyph_position_t &glyph_pos) const { unsigned int format = *this; - hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction); - if (!format) return; + hb_font_t *font = c->font; + hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); + if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++)); if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++)); if (format & xAdvance) { @@ -131,25 +131,26 @@ struct ValueFormat : USHORT bool use_x_device = font->x_ppem || font->num_coords; bool use_y_device = font->y_ppem || font->num_coords; - if (!use_x_device && !use_y_device) return; + const VarStore &store = c->var_store; + /* pixel -> fractional pixel */ if (format & xPlaDevice) { - if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font); + if (use_x_device) glyph_pos.x_offset += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yPlaDevice) { - if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font); + if (use_y_device) glyph_pos.y_offset += (base + get_device (values)).get_y_delta (font, store); values++; } if (format & xAdvDevice) { - if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font); + if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store); values++; } if (format & yAdvDevice) { /* y_advance values grow downward but font-space grows upward, hence negation */ - if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font); + if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store); values++; } } @@ -295,9 +296,9 @@ struct AnchorFormat3 *y = font->em_scale_y (yCoordinate); if (font->x_ppem || font->num_coords) - *x += (this+xDeviceTable).get_x_delta (font); + *x += (this+xDeviceTable).get_x_delta (font, c->var_store); if (font->y_ppem || font->num_coords) - *y += (this+yDeviceTable).get_x_delta (font); + *y += (this+yDeviceTable).get_x_delta (font, c->var_store); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -475,8 +476,7 @@ struct SinglePosFormat1 unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, - values, buffer->cur_pos()); + valueFormat.apply_value (c, this, values, buffer->cur_pos()); buffer->idx++; return_trace (true); @@ -526,7 +526,7 @@ struct SinglePosFormat2 if (likely (index >= valueCount)) return_trace (false); - valueFormat.apply_value (c->font, c->direction, this, + valueFormat.apply_value (c, this, &values[index * valueFormat.get_len ()], buffer->cur_pos()); @@ -643,10 +643,8 @@ struct PairSet min = mid + 1; else { - valueFormats[0].apply_value (c->font, c->direction, this, - &record->values[0], buffer->cur_pos()); - valueFormats[1].apply_value (c->font, c->direction, this, - &record->values[len1], buffer->pos[pos]); + valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); + valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (len2) pos++; buffer->idx = pos; @@ -793,10 +791,8 @@ struct PairPosFormat2 if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; - valueFormat1.apply_value (c->font, c->direction, this, - v, buffer->cur_pos()); - valueFormat2.apply_value (c->font, c->direction, this, - v + len1, buffer->pos[skippy_iter.idx]); + valueFormat1.apply_value (c, this, v, buffer->cur_pos()); + valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); buffer->idx = skippy_iter.idx; if (len2) diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 997d22550..1f501c694 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -469,6 +469,7 @@ struct hb_apply_context_t : unsigned int lookup_props; const GDEF &gdef; bool has_glyph_classes; + const VarStore &var_store; skipping_iterator_t iter_input, iter_context; unsigned int lookup_index; unsigned int debug_depth; @@ -487,6 +488,7 @@ struct hb_apply_context_t : lookup_props (0), gdef (*hb_ot_layout_from_face (face)->gdef), has_glyph_classes (gdef.has_glyph_classes ()), + var_store (gdef.get_var_store ()), iter_input (), iter_context (), lookup_index ((unsigned int) -1), From ad69e8f07c6e3e47fe7e7103c2ff7c053d272b1a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 22:23:34 -0700 Subject: [PATCH 0133/1326] [GX] Add new API hb_font_set_var_coords_normalized() Will probably change. --- src/hb-font.cc | 23 +++++++++++++++++++++++ src/hb-font.h | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index 978e7dd06..d27961db9 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1548,6 +1548,29 @@ hb_font_get_ppem (hb_font_t *font, } +void +hb_font_set_var_coords_normalized (hb_font_t *font, + int *coords, /* XXX 2.14 normalized */ + unsigned int coords_length) +{ + if (font->immutable) + return; + + int *copy = (int *) calloc (coords_length, sizeof (coords[0])); + if (unlikely (!copy)) + return; + + if (font->x_coords) + free (font->x_coords); + if (font->y_coords && font->y_coords != font->x_coords) + free (font->y_coords); + + memcpy (copy, coords, coords_length * sizeof (coords[0])); + font->x_coords = font->y_coords = copy; + font->num_coords = coords_length; +} + + #ifndef HB_DISABLE_DEPRECATED /* diff --git a/src/hb-font.h b/src/hb-font.h index 2b6ab5088..881328672 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -604,6 +604,11 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *y_ppem); +HB_EXTERN void +hb_font_set_var_coords_normalized (hb_font_t *font, + int *coords, /* XXX 2.14 normalized */ + unsigned int coords_length); + HB_END_DECLS #endif /* HB_FONT_H */ From 1124d2ece55e323ed934357b30e68df75829cfaa Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 22:48:27 -0700 Subject: [PATCH 0134/1326] [GX] Fix thinko --- src/hb-ot-layout-common-private.hh | 1 - src/hb-ot-layout-gpos-table.hh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 8c63ad983..35889c712 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1265,7 +1265,6 @@ struct VarData const BYTE *bytes = &StructAfter (regionIndices); const BYTE *row = bytes + inner * (scount + count); - float delta = 0.; unsigned int i = 0; diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 1893f0e4e..dd398f75c 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -298,7 +298,7 @@ struct AnchorFormat3 if (font->x_ppem || font->num_coords) *x += (this+xDeviceTable).get_x_delta (font, c->var_store); if (font->y_ppem || font->num_coords) - *y += (this+yDeviceTable).get_x_delta (font, c->var_store); + *y += (this+yDeviceTable).get_y_delta (font, c->var_store); } inline bool sanitize (hb_sanitize_context_t *c) const From 250bcd6fb691d6f15fa9ca71b475ce419d0b5e37 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 9 Sep 2016 23:12:14 -0700 Subject: [PATCH 0135/1326] [GX] Skip tail zero entries when setting variation coordinates --- src/hb-font.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index d27961db9..cce4359ce 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1556,6 +1556,10 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (font->immutable) return; + /* Skip tail zero entries. */ + while (coords_length && !coords[coords_length - 1]) + coords_length--; + int *copy = (int *) calloc (coords_length, sizeof (coords[0])); if (unlikely (!copy)) return; From 1f6ed356e0a849b61ce98b6a2f38d04d98c2191e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 00:01:10 -0700 Subject: [PATCH 0136/1326] [GX] Fix build with some compilers Eg. https://ci.appveyor.com/project/behdad/harfbuzz/build/1.0.48/job/o9mnd33kcdeeg30r hb-open-type-private.hh:103:29: error: static data member 'OT::Device::::::static_size' in unnamed class [-fpermissive] --- src/hb-ot-layout-common-private.hh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 35889c712..c18e52033 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1445,6 +1445,17 @@ struct VariationDevice DEFINE_SIZE_STATIC (6); }; +struct DeviceHeader +{ + protected: + USHORT reserved1; + USHORT reserved2; + public: + USHORT format; /* Format identifier */ + public: + DEFINE_SIZE_STATIC (6); +}; + struct Device { inline hb_position_t get_x_delta (hb_font_t *font, const VarStore &store) const @@ -1488,13 +1499,7 @@ struct Device protected: union { - struct { - USHORT reserved1; - USHORT reserved2; - USHORT format; /* Format identifier */ - public: - DEFINE_SIZE_STATIC (6); - } b; + DeviceHeader b; HintingDevice hinting; VariationDevice variation; } u; From cf3de4d8f79fc6e8413957cdef034e975343ce30 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 00:22:24 -0700 Subject: [PATCH 0137/1326] [GX] Rename VarStore to VariationStore --- src/hb-ot-layout-common-private.hh | 12 ++++++------ src/hb-ot-layout-gdef-table.hh | 14 +++++++------- src/hb-ot-layout-gpos-table.hh | 2 +- src/hb-ot-layout-gsubgpos-private.hh | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index c18e52033..c31a19711 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1303,7 +1303,7 @@ struct VarData DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX); }; -struct VarStore +struct VariationStore { inline float get_delta (unsigned int outer, unsigned int inner, int *coords, unsigned int coord_count) const @@ -1417,10 +1417,10 @@ struct VariationDevice private: - inline hb_position_t get_x_delta (hb_font_t *font, const VarStore &store) const + inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const { return font->em_scalef_x (get_delta (store, font->x_coords, font->num_coords)); } - inline hb_position_t get_y_delta (hb_font_t *font, const VarStore &store) const + inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const { return font->em_scalef_y (get_delta (store, font->y_coords, font->num_coords)); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -1431,7 +1431,7 @@ struct VariationDevice private: - inline float get_delta (const VarStore &store, + inline float get_delta (const VariationStore &store, int *coords, unsigned int coord_count) const { return store.get_delta (outerIndex, innerIndex, coords, coord_count); @@ -1458,7 +1458,7 @@ struct DeviceHeader struct Device { - inline hb_position_t get_x_delta (hb_font_t *font, const VarStore &store) const + inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const { switch (u.b.format) { @@ -1470,7 +1470,7 @@ struct Device return 0; } } - inline hb_position_t get_y_delta (hb_font_t *font, const VarStore &store) const + inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const { switch (u.b.format) { diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 2a92ece49..d85140e27 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -146,7 +146,7 @@ struct CaretValueFormat3 { friend struct CaretValue; - inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VarStore &var_store) const + inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const { return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : @@ -175,7 +175,7 @@ struct CaretValue inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VarStore &var_store) const + const VariationStore &var_store) const { switch (u.format) { case 1: return u.format1.get_caret_value (font, direction); @@ -213,7 +213,7 @@ struct LigGlyph inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VarStore &var_store, + const VariationStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -248,7 +248,7 @@ struct LigCaretList inline unsigned int get_lig_carets (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id, - const VarStore &var_store, + const VariationStore &var_store, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const @@ -381,8 +381,8 @@ struct GDEF { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; } - inline const VarStore &get_var_store (void) const - { return version.to_int () >= 0x00010003u ? this+varStore : Null(VarStore); } + inline const VariationStore &get_var_store (void) const + { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -444,7 +444,7 @@ struct GDEF * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 0x00010002. */ - OffsetTo + OffsetTo varStore; /* Offset to the table of Item Variation * Store--from beginning of GDEF * header (may be NULL). Introduced diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index dd398f75c..0ced5d03e 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -133,7 +133,7 @@ struct ValueFormat : USHORT if (!use_x_device && !use_y_device) return; - const VarStore &store = c->var_store; + const VariationStore &store = c->var_store; /* pixel -> fractional pixel */ if (format & xPlaDevice) { diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 1f501c694..5cb6ba7c3 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -469,7 +469,7 @@ struct hb_apply_context_t : unsigned int lookup_props; const GDEF &gdef; bool has_glyph_classes; - const VarStore &var_store; + const VariationStore &var_store; skipping_iterator_t iter_input, iter_context; unsigned int lookup_index; unsigned int debug_depth; From 85ec4944346a1ac111217698e1424669a9732280 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 00:25:16 -0700 Subject: [PATCH 0138/1326] [GX] Fix another x/y thinko Thanks Werner! --- src/hb-ot-layout-common-private.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index c31a19711..3f835f13d 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1475,7 +1475,7 @@ struct Device switch (u.b.format) { case 1: case 2: case 3: - return u.hinting.get_x_delta (font); + return u.hinting.get_y_delta (font); case 0x8000: return u.variation.get_y_delta (font, store); default: From 59055b5494f802013ca3613a15e565ae1ca0c589 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 01:24:28 -0700 Subject: [PATCH 0139/1326] [GX] Implement Feature Variations Not hooked up to shaper yet. --- src/hb-ot-layout-common-private.hh | 168 ++++++++++++++++++++++++++- src/hb-ot-layout-gdef-table.hh | 1 - src/hb-ot-layout-gpos-table.hh | 2 - src/hb-ot-layout-gsub-table.hh | 2 - src/hb-ot-layout-gsubgpos-private.hh | 15 ++- 5 files changed, 180 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 3f835f13d..fb99ec3e0 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -507,7 +507,7 @@ struct Feature { return this+featureParams; } inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t *closure) const + const Record::sanitize_closure_t *closure = NULL) const { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) @@ -1333,6 +1333,172 @@ struct VariationStore DEFINE_SIZE_ARRAY (8, dataSets); }; +/* + * Feature Variations + */ + +struct ConditionFormat1 +{ + friend struct Condition; + + private: + inline bool evaluate (int *coords, unsigned int coord_len) const + { + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; + return filterRangeMinValue <= coord && coord <= filterRangeMaxValue; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + USHORT format; /* Format identifier--format = 1 */ + USHORT axisIndex; + F2DOT14 filterRangeMinValue; + F2DOT14 filterRangeMaxValue; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Condition +{ + inline bool evaluate (int *coords, unsigned int coord_len) const + { + switch (u.format) { + case 1: return u.format1.evaluate (coords, coord_len); + default:return false; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { + case 1: return_trace (u.format1.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + USHORT format; /* Format identifier */ + ConditionFormat1 format1; + } u; + public: + DEFINE_SIZE_UNION (2, format); +}; + +struct ConditionSet +{ + inline bool evaluate (int *coords, unsigned int coord_len) const + { + unsigned int count = conditions.len; + for (unsigned int i = 0; i < count; i++) + if (!(this+conditions.array[i]).evaluate (coords, coord_len)) + return false; + return true; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, this)); + } + + protected: + OffsetArrayOf conditions; + public: + DEFINE_SIZE_ARRAY (2, conditions); +}; + +struct FeatureTableSubstitutionRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && feature.sanitize (c, this)); + } + + protected: + USHORT featureIndex; + OffsetTo feature; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct FeatureTableSubstitution +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + substitutions.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + OffsetArrayOf + substitutions; + public: + DEFINE_SIZE_ARRAY (6, substitutions); +}; + +struct FeatureVariationRecord +{ + friend struct FeatureVariations; + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (conditions.sanitize (c, base) && + substitutions.sanitize (c, base)); + } + + protected: + OffsetTo + conditions; + OffsetTo + substitutions; + public: + DEFINE_SIZE_STATIC (8); +}; + +struct FeatureVariations +{ + inline const FeatureTableSubstitution & + get_substitutions (int *coords, unsigned int coord_len) const + { + unsigned int count = varRecords.len; + for (unsigned int i = 0; i < count; i++) + { + const FeatureVariationRecord &record = varRecords.array[i]; + if ((this+record.conditions).evaluate (coords, coord_len)) + return (this+record.substitutions); + } + return Null(FeatureTableSubstitution); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varRecords.sanitize (c, this)); + } + + protected: + FixedVersion<> version; /* Version--0x00010000u */ + ArrayOf + varRecords; + public: + DEFINE_SIZE_ARRAY (8, varRecords); +}; + /* * Device Tables diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index d85140e27..b70cbb7a3 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -397,7 +397,6 @@ struct GDEF (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); } - /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing * glyph class and other bits, and high 8-bit gthe mark attachment type (if any). * Not to be confused with lookup_props which is very similar. */ diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 0ced5d03e..5c9fc29ca 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1518,8 +1518,6 @@ struct GPOS : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 22031f43c..6658a2cd9 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1273,8 +1273,6 @@ struct GSUB : GSUBGPOS const OffsetTo &list = CastR > (lookupList); return_trace (list.sanitize (c, this)); } - public: - DEFINE_SIZE_STATIC (10); }; diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 5cb6ba7c3..490b91e1b 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2271,6 +2271,11 @@ struct GSUBGPOS inline const Lookup& get_lookup (unsigned int i) const { return (this+lookupList)[i]; } + inline const FeatureTableSubstitution & + get_feature_substitutions (int *coords, unsigned int coord_len) const + { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) + .get_substitutions (coords, coord_len); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -2278,7 +2283,8 @@ struct GSUBGPOS likely (version.major == 1) && scriptList.sanitize (c, this) && featureList.sanitize (c, this) && - lookupList.sanitize (c, this)); + lookupList.sanitize (c, this) && + (version.to_int () < 0x00010001u || featureVars.sanitize (c, this))); } protected: @@ -2290,8 +2296,13 @@ struct GSUBGPOS featureList; /* FeatureList table */ OffsetTo lookupList; /* LookupList table */ + OffsetTo + featureVars; /* Offset to Feature Variations + table--from beginning of table + * (may be NULL). Introduced + * in version 0x00010001. */ public: - DEFINE_SIZE_STATIC (10); + DEFINE_SIZE_MIN (10); }; From c22176d4bac720b4c9121b3d6629595831f19fb0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 01:58:27 -0700 Subject: [PATCH 0140/1326] [GX] Handle setting var coords to NULL --- src/hb-font.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index cce4359ce..24ecb4502 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1560,8 +1560,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font, while (coords_length && !coords[coords_length - 1]) coords_length--; - int *copy = (int *) calloc (coords_length, sizeof (coords[0])); - if (unlikely (!copy)) + int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL; + if (unlikely (coords_length && !copy)) return; if (font->x_coords) @@ -1569,7 +1569,9 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (font->y_coords && font->y_coords != font->x_coords) free (font->y_coords); - memcpy (copy, coords, coords_length * sizeof (coords[0])); + if (coords_length) + memcpy (copy, coords, coords_length * sizeof (coords[0])); + font->x_coords = font->y_coords = copy; font->num_coords = coords_length; } From 26648cebcd14bd26142ccfe5ac8c0be08a213671 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 02:11:05 -0700 Subject: [PATCH 0141/1326] [GX] Remove (partial) support for anisotropic variations It doesn't always work, not part of FreeType, and we were not going to expose it in the API anyway. Can always be added later. --- src/hb-font-private.hh | 3 +-- src/hb-font.cc | 17 ++++++----------- src/hb-ot-layout-common-private.hh | 9 ++++----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 48dc72564..53671d78d 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -110,8 +110,7 @@ struct hb_font_t { /* Font variation coordinates. */ unsigned int num_coords; - int *x_coords; - int *y_coords; + int *coords; hb_font_funcs_t *klass; void *user_data; diff --git a/src/hb-font.cc b/src/hb-font.cc index 24ecb4502..f12dfb5d3 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1197,8 +1197,7 @@ hb_font_get_empty (void) 0, /* y_ppem */ 0, /* num_coords */ - NULL, /* x_coords */ - NULL, /* y_coords */ + NULL, /* coords */ const_cast (&_hb_font_funcs_nil), /* klass */ NULL, /* user_data */ @@ -1254,10 +1253,8 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - if (font->x_coords) - free (font->x_coords); - if (font->y_coords && font->y_coords != font->x_coords) - free (font->y_coords); + if (font->coords) + free (font->coords); free (font); } @@ -1564,15 +1561,13 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (unlikely (coords_length && !copy)) return; - if (font->x_coords) - free (font->x_coords); - if (font->y_coords && font->y_coords != font->x_coords) - free (font->y_coords); + if (font->coords) + free (font->coords); if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); - font->x_coords = font->y_coords = copy; + font->coords = copy; font->num_coords = coords_length; } diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index fb99ec3e0..3c574af70 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1584,10 +1584,10 @@ struct VariationDevice private: inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const - { return font->em_scalef_x (get_delta (store, font->x_coords, font->num_coords)); } + { return font->em_scalef_x (get_delta (font, store)); } inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const - { return font->em_scalef_y (get_delta (store, font->y_coords, font->num_coords)); } + { return font->em_scalef_y (get_delta (font, store)); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1597,10 +1597,9 @@ struct VariationDevice private: - inline float get_delta (const VariationStore &store, - int *coords, unsigned int coord_count) const + inline float get_delta (hb_font_t *font, const VariationStore &store) const { - return store.get_delta (outerIndex, innerIndex, coords, coord_count); + return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords); } protected: From bde5e3959c0ffdb92db87668035b01aaee9b2352 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 02:43:20 -0700 Subject: [PATCH 0142/1326] Move add_lookups from map to map-builder In prep for more changes. --- src/hb-ot-map-private.hh | 15 ++++++++------- src/hb-ot-map.cc | 29 +++++++++++++++-------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 8692caa93..fc5ce6637 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -139,12 +139,6 @@ struct hb_ot_map_t private: - HB_INTERNAL void add_lookups (hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj); - hb_mask_t global_mask; hb_prealloced_array_t features; @@ -182,7 +176,7 @@ struct hb_ot_map_builder_t inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (1, pause_func); } - HB_INTERNAL void compile (struct hb_ot_map_t &m); + HB_INTERNAL void compile (hb_ot_map_t &m); inline void finish (void) { feature_infos.finish (); @@ -194,6 +188,13 @@ struct hb_ot_map_builder_t private: + HB_INTERNAL void add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + hb_mask_t mask, + bool auto_zwj); + struct feature_info_t { hb_tag_t tag; unsigned int seq; /* sequence#, used for stable sorting only */ diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 17e3f4065..a45c2f9e8 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -32,11 +32,12 @@ void -hb_ot_map_t::add_lookups (hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj) +hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + hb_mask_t mask, + bool auto_zwj) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -57,7 +58,7 @@ hb_ot_map_t::add_lookups (hb_face_t *face, { if (lookup_indices[i] >= table_lookup_count) continue; - hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push (); + hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push (); if (unlikely (!lookup)) return; lookup->mask = mask; @@ -268,17 +269,17 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX && required_feature_stage[table_index] == stage) - m.add_lookups (face, table_index, - required_feature_index[table_index], - 1 /* mask */, - true /* auto_zwj */); + add_lookups (m, face, table_index, + required_feature_index[table_index], + 1 /* mask */, + true /* auto_zwj */); for (unsigned i = 0; i < m.features.len; i++) if (m.features[i].stage[table_index] == stage) - m.add_lookups (face, table_index, - m.features[i].index[table_index], - m.features[i].mask, - m.features[i].auto_zwj); + add_lookups (m, face, table_index, + m.features[i].index[table_index], + m.features[i].mask, + m.features[i].auto_zwj); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].len) From 7ceadbe981aa50481163bb365f0fe3f994266165 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 02:44:20 -0700 Subject: [PATCH 0143/1326] Shuffle code around --- src/hb-ot-map.cc | 81 ++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index a45c2f9e8..9cd3a4472 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -31,45 +31,13 @@ #include "hb-ot-layout-private.hh" -void -hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, - hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj) +void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const { - unsigned int lookup_indices[32]; - unsigned int offset, len; - unsigned int table_lookup_count; - - table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]); - - offset = 0; - do { - len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tags[table_index], - feature_index, - offset, &len, - lookup_indices); - - for (unsigned int i = 0; i < len; i++) - { - if (lookup_indices[i] >= table_lookup_count) - continue; - hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push (); - if (unlikely (!lookup)) - return; - lookup->mask = mask; - lookup->index = lookup_indices[i]; - lookup->auto_zwj = auto_zwj; - } - - offset += len; - } while (len == ARRAY_LENGTH (lookup_indices)); + for (unsigned int i = 0; i < lookups[table_index].len; i++) + hb_set_add (lookups_out, lookups[table_index][i].index); } + hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_, const hb_segment_properties_t *props_) { @@ -110,13 +78,46 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, info->stage[1] = current_stage[1]; } - -void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const +void +hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + hb_mask_t mask, + bool auto_zwj) { - for (unsigned int i = 0; i < lookups[table_index].len; i++) - hb_set_add (lookups_out, lookups[table_index][i].index); + unsigned int lookup_indices[32]; + unsigned int offset, len; + unsigned int table_lookup_count; + + table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]); + + offset = 0; + do { + len = ARRAY_LENGTH (lookup_indices); + hb_ot_layout_feature_get_lookups (face, + table_tags[table_index], + feature_index, + offset, &len, + lookup_indices); + + for (unsigned int i = 0; i < len; i++) + { + if (lookup_indices[i] >= table_lookup_count) + continue; + hb_ot_map_t::lookup_map_t *lookup = m.lookups[table_index].push (); + if (unlikely (!lookup)) + return; + lookup->mask = mask; + lookup->index = lookup_indices[i]; + lookup->auto_zwj = auto_zwj; + } + + offset += len; + } while (len == ARRAY_LENGTH (lookup_indices)); } + void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func) { stage_info_t *s = stages[table_index].push (); From 30c42b644eb33551aa0986287182a46f2d8c32ed Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 03:32:39 -0700 Subject: [PATCH 0144/1326] [GX] Add hb_ot_layout_table_find_feature_variations() --- src/hb-ot-layout-common-private.hh | 18 +++++++++++------- src/hb-ot-layout-gsubgpos-private.hh | 6 +++--- src/hb-ot-layout.cc | 15 +++++++++++++++ src/hb-ot-layout.h | 10 ++++++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 3c574af70..e67a5145d 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1342,7 +1342,7 @@ struct ConditionFormat1 friend struct Condition; private: - inline bool evaluate (int *coords, unsigned int coord_len) const + inline bool evaluate (const int *coords, unsigned int coord_len) const { int coord = axisIndex < coord_len ? coords[axisIndex] : 0; return filterRangeMinValue <= coord && coord <= filterRangeMaxValue; @@ -1365,7 +1365,7 @@ struct ConditionFormat1 struct Condition { - inline bool evaluate (int *coords, unsigned int coord_len) const + inline bool evaluate (const int *coords, unsigned int coord_len) const { switch (u.format) { case 1: return u.format1.evaluate (coords, coord_len); @@ -1394,7 +1394,7 @@ struct Condition struct ConditionSet { - inline bool evaluate (int *coords, unsigned int coord_len) const + inline bool evaluate (const int *coords, unsigned int coord_len) const { unsigned int count = conditions.len; for (unsigned int i = 0; i < count; i++) @@ -1470,17 +1470,21 @@ struct FeatureVariationRecord struct FeatureVariations { - inline const FeatureTableSubstitution & - get_substitutions (int *coords, unsigned int coord_len) const + inline bool find_index (const int *coords, unsigned int coord_len, + unsigned int *index) const { unsigned int count = varRecords.len; for (unsigned int i = 0; i < count; i++) { const FeatureVariationRecord &record = varRecords.array[i]; if ((this+record.conditions).evaluate (coords, coord_len)) - return (this+record.substitutions); + { + *index = i; + return true; + } } - return Null(FeatureTableSubstitution); + *index = 0xFFFFFFFF; + return false; } inline bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 490b91e1b..e20777acb 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2271,10 +2271,10 @@ struct GSUBGPOS inline const Lookup& get_lookup (unsigned int i) const { return (this+lookupList)[i]; } - inline const FeatureTableSubstitution & - get_feature_substitutions (int *coords, unsigned int coord_len) const + inline bool find_variations_index (const int *coords, unsigned int num_coords, + unsigned int *index) const { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) - .get_substitutions (coords, coord_len); } + .find_index (coords, num_coords, index); } inline bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0501181a3..b352cdb5d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -836,6 +836,21 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, } +/* Variations support */ + +hb_bool_t +hb_ot_layout_table_find_feature_variations (hb_face_t *face, + hb_tag_t table_tag, + const int *coords, + unsigned int num_coords, + unsigned int *variations_index /* out */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + return g.find_variations_index (coords, num_coords, variations_index); +} + + /* * OT::GSUB */ diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index eb23d45b6..2e3db8c20 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -95,6 +95,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, #define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu +#define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu HB_EXTERN unsigned int hb_ot_layout_table_get_script_tags (hb_face_t *face, @@ -236,6 +237,15 @@ Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, void *user_data); #endif +/* Variations support */ + +HB_EXTERN hb_bool_t +hb_ot_layout_table_find_feature_variations (hb_face_t *face, + hb_tag_t table_tag, + const int *coords, + unsigned int num_coords, + unsigned int *variations_index /* out */); + /* * GSUB From ec87ba9ba32a374d49dd3e40137f75f4f4232aee Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 03:53:11 -0700 Subject: [PATCH 0145/1326] [GX] Add hb_ot_layout_feature_with_variations_get_lookups() --- src/hb-ot-layout-common-private.hh | 30 +++++++++++++++++++++++++++- src/hb-ot-layout-gsubgpos-private.hh | 12 +++++++++++ src/hb-ot-layout.cc | 28 ++++++++++++++++++++++---- src/hb-ot-layout.h | 9 +++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index e67a5145d..cdf43bf40 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1417,6 +1417,13 @@ struct ConditionSet struct FeatureTableSubstitutionRecord { + inline const Feature *find_substitute (unsigned int feature_index) const + { + if (featureIndex == feature_index) + return &(this+feature); + return NULL; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1432,6 +1439,18 @@ struct FeatureTableSubstitutionRecord struct FeatureTableSubstitution { + inline const Feature *find_substitute (unsigned int feature_index) const + { + unsigned int count = substitutions.len; + for (unsigned int i = 0; i < count; i++) + { + const Feature *feature = (this+substitutions.array[i]).find_substitute (feature_index); + if (feature) + return feature; + } + return NULL; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1470,6 +1489,8 @@ struct FeatureVariationRecord struct FeatureVariations { + static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu; + inline bool find_index (const int *coords, unsigned int coord_len, unsigned int *index) const { @@ -1483,10 +1504,17 @@ struct FeatureVariations return true; } } - *index = 0xFFFFFFFF; + *index = NOT_FOUND_INDEX; return false; } + inline const Feature *find_substitute (unsigned int variations_index, + unsigned int feature_index) const + { + const FeatureVariationRecord &record = varRecords[variations_index]; + return (this+record.substitutions).find_substitute (feature_index); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index e20777acb..adea32f23 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2275,6 +2275,18 @@ struct GSUBGPOS unsigned int *index) const { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations)) .find_index (coords, num_coords, index); } + inline const Feature& get_feature_variation (unsigned int feature_index, + unsigned int variations_index) const + { + if (FeatureVariations::NOT_FOUND_INDEX != variations_index && + version.to_int () >= 0x00010001u) + { + const Feature *feature = (this+featureVars).find_substitute (variations_index, feature_index); + if (feature) + return *feature; + } + return get_feature (feature_index); + } inline bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index b352cdb5d..345d5e695 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -582,10 +582,13 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { - const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const OT::Feature &f = g.get_feature (feature_index); - - return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); + return hb_ot_layout_feature_with_variations_get_lookups (face, + table_tag, + feature_index, + HB_OT_LAYOUT_NO_VARIATIONS_INDEX, + start_offset, + lookup_count, + lookup_indexes); } /** @@ -850,6 +853,23 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face, return g.find_variations_index (coords, num_coords, variations_index); } +unsigned int +hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int variations_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */) +{ + ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + const OT::Feature &f = g.get_feature_variation (feature_index, variations_index); + + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); +} + /* * OT::GSUB diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 2e3db8c20..9861f0fc7 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -246,6 +246,15 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face, unsigned int num_coords, unsigned int *variations_index /* out */); +HB_EXTERN unsigned int +hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int variations_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */); + /* * GSUB From 72ada4f0c6998fc2a282efc2a573733e37db8be5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 03:57:24 -0700 Subject: [PATCH 0146/1326] [GX] Hook up feature variations Shape-plan caching is not implemented. --- src/hb-coretext.cc | 8 ++- src/hb-directwrite.cc | 6 ++- src/hb-fallback-shape.cc | 4 +- src/hb-font.cc | 6 +-- src/hb-graphite2.cc | 4 +- src/hb-ot-map-private.hh | 17 +++--- src/hb-ot-map.cc | 25 ++++++--- src/hb-ot-shape-private.hh | 6 ++- src/hb-ot-shape.cc | 9 ++-- src/hb-shape-plan-private.hh | 9 +++- src/hb-shape-plan.cc | 102 +++++++++++++++++++++++++++++++---- src/hb-shape-plan.h | 19 +++++++ src/hb-shape.cc | 5 +- src/hb-uniscribe.cc | 4 +- 14 files changed, 183 insertions(+), 41 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 507581bd7..e857dfae0 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -288,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {}; hb_coretext_shaper_shape_plan_data_t * _hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -1280,7 +1282,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {}; hb_coretext_aat_shaper_shape_plan_data_t * _hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 76482acd3..d26b29851 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -258,8 +258,10 @@ struct hb_directwrite_shaper_shape_plan_data_t {}; hb_directwrite_shaper_shape_plan_data_t * _hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, - const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + const hb_feature_t *user_features HB_UNUSED, + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index e2ad24001..ac6d4b00f 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -73,7 +73,9 @@ struct hb_fallback_shaper_shape_plan_data_t {}; hb_fallback_shaper_shape_plan_data_t * _hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-font.cc b/src/hb-font.cc index f12dfb5d3..2935c4b4f 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1253,8 +1253,7 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - if (font->coords) - free (font->coords); + free (font->coords); free (font); } @@ -1561,8 +1560,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (unlikely (coords_length && !copy)) return; - if (font->coords) - free (font->coords); + free (font->coords); if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index c32318d27..a2d90db87 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -195,7 +195,9 @@ struct hb_graphite2_shaper_shape_plan_data_t {}; hb_graphite2_shaper_shape_plan_data_t * _hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index fc5ce6637..0395c9c22 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -176,7 +176,9 @@ struct hb_ot_map_builder_t inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (1, pause_func); } - HB_INTERNAL void compile (hb_ot_map_t &m); + HB_INTERNAL void compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords); inline void finish (void) { feature_infos.finish (); @@ -188,12 +190,13 @@ struct hb_ot_map_builder_t private: - HB_INTERNAL void add_lookups (hb_ot_map_t &m, - hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj); + HB_INTERNAL void add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + unsigned int variations_index, + hb_mask_t mask, + bool auto_zwj); struct feature_info_t { hb_tag_t tag; diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 9cd3a4472..9b331d521 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -83,6 +83,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, hb_face_t *face, unsigned int table_index, unsigned int feature_index, + unsigned int variations_index, hb_mask_t mask, bool auto_zwj) { @@ -95,11 +96,12 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, offset = 0; do { len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tags[table_index], - feature_index, - offset, &len, - lookup_indices); + hb_ot_layout_feature_with_variations_get_lookups (face, + table_tags[table_index], + feature_index, + variations_index, + offset, &len, + lookup_indices); for (unsigned int i = 0; i < len; i++) { @@ -130,7 +132,9 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus } void -hb_ot_map_builder_t::compile (hb_ot_map_t &m) +hb_ot_map_builder_t::compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords) { m.global_mask = 1; @@ -264,6 +268,13 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { /* Collect lookup indices for features */ + unsigned int variations_index; + hb_ot_layout_table_find_feature_variations (face, + table_tags[table_index], + coords, + num_coords, + &variations_index); + unsigned int stage_index = 0; unsigned int last_num_lookups = 0; for (unsigned stage = 0; stage < current_stage[table_index]; stage++) @@ -272,6 +283,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) required_feature_stage[table_index] == stage) add_lookups (m, face, table_index, required_feature_index[table_index], + variations_index, 1 /* mask */, true /* auto_zwj */); @@ -279,6 +291,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) if (m.features[i].stage[table_index] == stage) add_lookups (m, face, table_index, m.features[i].index[table_index], + variations_index, m.features[i].mask, m.features[i].auto_zwj); diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh index 54ac2c3cf..594e54c02 100644 --- a/src/hb-ot-shape-private.hh +++ b/src/hb-ot-shape-private.hh @@ -77,11 +77,13 @@ struct hb_ot_shape_planner_t map (face, &props) {} ~hb_ot_shape_planner_t (void) { map.finish (); } - inline void compile (hb_ot_shape_plan_t &plan) + inline void compile (hb_ot_shape_plan_t &plan, + const int *coords, + unsigned int num_coords) { plan.props = props; plan.shaper = shaper; - map.compile (plan.map); + map.compile (plan.map, coords, num_coords); plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7811cb7f8..6c78b4752 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -163,7 +163,9 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data) hb_ot_shaper_shape_plan_data_t * _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, - unsigned int num_user_features) + unsigned int num_user_features, + const int *coords, + unsigned int num_coords) { hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); if (unlikely (!plan)) @@ -173,9 +175,10 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, planner.shaper = hb_ot_shape_complex_categorize (&planner); - hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features); + hb_ot_shape_collect_features (&planner, &shape_plan->props, + user_features, num_user_features); - planner.compile (*plan); + planner.compile (*plan, coords, num_coords); if (plan->shaper->data_create) { plan->data = plan->shaper->data_create (plan); diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh index 607da5e77..aa0413a27 100644 --- a/src/hb-shape-plan-private.hh +++ b/src/hb-shape-plan-private.hh @@ -47,12 +47,17 @@ struct hb_shape_plan_t hb_feature_t *user_features; unsigned int num_user_features; + int *coords; + unsigned int num_coords; + struct hb_shaper_data_t shaper_data; }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \ - , const hb_feature_t *user_features \ - , unsigned int num_user_features + , const hb_feature_t *user_features \ + , unsigned int num_user_features \ + , const int *coords \ + , unsigned int num_coords #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 87231fb33..600faaeb1 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -46,11 +46,14 @@ static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, unsigned int num_user_features, + const int *coords, + unsigned int num_coords, const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d shaper_list=%p", + "num_features=%d num_coords=%d shaper_list=%p", num_user_features, + num_coords, shaper_list); const hb_shaper_pair_t *shapers = _hb_shapers_get (); @@ -59,7 +62,9 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, HB_STMT_START { \ if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ - HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ + HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \ + user_features, num_user_features, \ + coords, num_coords); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ shape_plan->shaper_name = #shaper; \ return; \ @@ -114,15 +119,32 @@ hb_shape_plan_create (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *orig_coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, - "face=%p num_features=%d shaper_list=%p", + "face=%p num_features=%d num_coords=%d shaper_list=%p", face, num_user_features, + num_coords, shaper_list); hb_shape_plan_t *shape_plan; hb_feature_t *features = NULL; + int *coords = NULL; if (unlikely (!face)) face = hb_face_get_empty (); @@ -130,7 +152,14 @@ hb_shape_plan_create (hb_face_t *face, return hb_shape_plan_get_empty (); if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create ())) { + if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int)))) + { + free (features); + return hb_shape_plan_get_empty (); + } + if (!(shape_plan = hb_object_create ())) + { + free (coords); free (features); return hb_shape_plan_get_empty (); } @@ -145,8 +174,15 @@ hb_shape_plan_create (hb_face_t *face, shape_plan->user_features = features; if (num_user_features) memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + shape_plan->num_coords = num_coords; + shape_plan->coords = coords; + if (num_coords) + memcpy (coords, orig_coords, num_coords * sizeof (int)); - hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); + hb_shape_plan_plan (shape_plan, + user_features, num_user_features, + coords, num_coords, + shaper_list); return shape_plan; } @@ -176,6 +212,9 @@ hb_shape_plan_get_empty (void) NULL, /* user_features */ 0, /* num_user_featurs */ + NULL, /* coords */ + 0, /* num_coords */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -220,6 +259,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #undef HB_SHAPER_IMPLEMENT free (shape_plan->user_features); + free (shape_plan->coords); free (shape_plan); } @@ -351,6 +391,8 @@ struct hb_shape_plan_proposal_t const char * const *shaper_list; const hb_feature_t *user_features; unsigned int num_user_features; + const int *coords; + unsigned int num_coords; hb_shape_func_t *shaper_func; }; @@ -358,12 +400,26 @@ static inline hb_bool_t hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { - if (proposal->num_user_features != shape_plan->num_user_features) return false; + if (proposal->num_user_features != shape_plan->num_user_features) + return false; for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || proposal->user_features[i].value != shape_plan->user_features[i].value || proposal->user_features[i].start != shape_plan->user_features[i].start || - proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + proposal->user_features[i].end != shape_plan->user_features[i].end) + return false; + return true; +} + +static inline hb_bool_t +hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_coords != shape_plan->num_coords) + return false; + for (unsigned int i = 0, n = proposal->num_coords; i < n; i++) + if (proposal->coords[i] != shape_plan->coords[i]) + return false; return true; } @@ -373,6 +429,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && hb_shape_plan_user_features_match (shape_plan, proposal) && + hb_shape_plan_coords_match (shape_plan, proposal) && ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || (shape_plan->shaper_func == proposal->shaper_func)); } @@ -389,6 +446,13 @@ hb_non_global_user_features_present (const hb_feature_t *user_features, return false; } +static inline hb_bool_t +hb_coords_present (const int *coords, + unsigned int num_coords) +{ + return num_coords != 0; +} + /** * hb_shape_plan_create_cached: * @face: @@ -409,6 +473,21 @@ hb_shape_plan_create_cached (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create_cached2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, "face=%p num_features=%d shaper_list=%p", @@ -456,16 +535,21 @@ retry: /* Not found. */ - hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, + user_features, num_user_features, + coords, num_coords, + shaper_list); /* Don't add to the cache if face is inert. */ if (unlikely (hb_object_is_inert (face))) return shape_plan; /* Don't add the plan to the cache if there were user features with non-global ranges */ - if (hb_non_global_user_features_present (user_features, num_user_features)) return shape_plan; + /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */ + if (hb_coords_present (coords, num_coords)) + return shape_plan; hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); if (unlikely (!node)) diff --git a/src/hb-shape-plan.h b/src/hb-shape-plan.h index aa5e0c7d6..b62ae7ca3 100644 --- a/src/hb-shape-plan.h +++ b/src/hb-shape-plan.h @@ -52,6 +52,25 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list); +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + + HB_EXTERN hb_shape_plan_t * hb_shape_plan_get_empty (void); diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 41a4fc500..706f14420 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -373,7 +373,10 @@ hb_shape_full (hb_font_t *font, unsigned int num_features, const char * const *shaper_list) { - hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props, + features, num_features, + font->coords, font->num_coords, + shaper_list); hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 07007a640..6e4db0149 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -587,7 +587,9 @@ struct hb_uniscribe_shaper_shape_plan_data_t {}; hb_uniscribe_shaper_shape_plan_data_t * _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } From 4ebbeb7c50e5c1e934d230ceacf792602c6eb9b9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 10 Sep 2016 04:52:34 -0700 Subject: [PATCH 0147/1326] [GX] Make FeatureVariations actually work Yay!!!! --- src/hb-ot-layout-common-private.hh | 19 +++++++------------ src/hb-ot-layout-gsubgpos-private.hh | 3 ++- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index cdf43bf40..971c95a0a 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1417,17 +1417,12 @@ struct ConditionSet struct FeatureTableSubstitutionRecord { - inline const Feature *find_substitute (unsigned int feature_index) const - { - if (featureIndex == feature_index) - return &(this+feature); - return NULL; - } + friend struct FeatureTableSubstitution; - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && feature.sanitize (c, this)); + return_trace (c->check_struct (this) && feature.sanitize (c, base)); } protected: @@ -1444,9 +1439,9 @@ struct FeatureTableSubstitution unsigned int count = substitutions.len; for (unsigned int i = 0; i < count; i++) { - const Feature *feature = (this+substitutions.array[i]).find_substitute (feature_index); - if (feature) - return feature; + const FeatureTableSubstitutionRecord &record = substitutions.array[i]; + if (record.featureIndex == feature_index) + return &(this+record.feature); } return NULL; } @@ -1461,7 +1456,7 @@ struct FeatureTableSubstitution protected: FixedVersion<> version; /* Version--0x00010000u */ - OffsetArrayOf + ArrayOf substitutions; public: DEFINE_SIZE_ARRAY (6, substitutions); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index adea32f23..b90af9ca0 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2281,7 +2281,8 @@ struct GSUBGPOS if (FeatureVariations::NOT_FOUND_INDEX != variations_index && version.to_int () >= 0x00010001u) { - const Feature *feature = (this+featureVars).find_substitute (variations_index, feature_index); + const Feature *feature = (this+featureVars).find_substitute (variations_index, + feature_index); if (feature) return *feature; } From 72873cf522a6e3bec1b6508d8d20d3d2ce233cd6 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Tue, 13 Sep 2016 18:40:07 +0200 Subject: [PATCH 0148/1326] Call hb_font_set_var_coords_normalized() from FT_Face coords --- src/hb-ft.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 2b06c59be..30d28c09e 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -36,6 +36,7 @@ #include "hb-cache-private.hh" // Maybe use in the future? #include FT_ADVANCES_H +#include FT_MULTIPLE_MASTERS_H #include FT_TRUETYPE_TABLES_H @@ -616,6 +617,19 @@ hb_ft_font_create (FT_Face ft_face, ft_face->size->metrics.y_ppem); #endif + FT_MM_Var *mm_var = NULL; + if (!FT_Get_MM_Var (ft_face, &mm_var)) { + FT_Fixed coords[mm_var->num_axis]; + int hbCoords[mm_var->num_axis]; + if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords)) { + for (int i = 0; i < mm_var->num_axis; ++i) { + hbCoords[i] = coords[i] >> 2; + } + hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis); + } + } + free (mm_var); + return font; } From 42c81425316190f6424ecb9b19d5a886aa1e4136 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 13 Sep 2016 23:49:46 +0200 Subject: [PATCH 0149/1326] [GX] Fix build with older FreeType --- configure.ac | 4 ++++ src/hb-ft.cc | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 0fdaf531e..6948aa6ff 100644 --- a/configure.ac +++ b/configure.ac @@ -346,6 +346,10 @@ if test "x$with_freetype" = "xyes" -a "x$have_freetype" != "xtrue"; then fi if $have_freetype; then AC_DEFINE(HAVE_FREETYPE, 1, [Have FreeType 2 library]) + save_libs=$LIBS + LIBS="$LIBS $FREETYPE_LIBS" + AC_CHECK_FUNCS(FT_Get_Var_Blend_Coordinates) + LIBS=$save_libs fi AM_CONDITIONAL(HAVE_FREETYPE, $have_freetype) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 30d28c09e..f127066a6 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -617,18 +617,22 @@ hb_ft_font_create (FT_Face ft_face, ft_face->size->metrics.y_ppem); #endif +#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES FT_MM_Var *mm_var = NULL; - if (!FT_Get_MM_Var (ft_face, &mm_var)) { + if (!FT_Get_MM_Var (ft_face, &mm_var)) + { FT_Fixed coords[mm_var->num_axis]; int hbCoords[mm_var->num_axis]; - if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords)) { - for (int i = 0; i < mm_var->num_axis; ++i) { + if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords)) + { + for (int i = 0; i < mm_var->num_axis; ++i) hbCoords[i] = coords[i] >> 2; - } + hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis); } } free (mm_var); +#endif return font; } From 0aedfd59be54972e61a952753ffc0d12631771fe Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Sep 2016 17:05:43 +0200 Subject: [PATCH 0150/1326] [GX] Apply 'rvrn' feature before any other feature --- src/hb-ot-shape.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 6c78b4752..987279878 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -69,6 +69,9 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, { hb_ot_map_builder_t *map = &planner->map; + map->add_global_bool_feature (HB_TAG('r','v','r','n')); + map->add_gsub_pause (NULL); + switch (props->direction) { case HB_DIRECTION_LTR: map->add_global_bool_feature (HB_TAG ('l','t','r','a')); From 219cb29c5d230ecc6ee154b447fabd7b59fbe089 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Sep 2016 17:16:06 +0200 Subject: [PATCH 0151/1326] Fix build after rebasing opentype-gx branch on top of MATH table --- src/hb-ot-layout-common-private.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 971c95a0a..4c7714a8e 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1650,7 +1650,7 @@ struct DeviceHeader struct Device { - inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const + inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const { switch (u.b.format) { @@ -1662,7 +1662,7 @@ struct Device return 0; } } - inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const + inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const { switch (u.b.format) { From 75fa884f925c203a839b5874f30bf9ebf025b6e4 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Mon, 5 Dec 2016 23:20:47 +0200 Subject: [PATCH 0152/1326] [win32] Fix wrong description of the ICU option (#372) --- win32/README.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/win32/README.txt b/win32/README.txt index 07e211c0a..af0dc15c1 100644 --- a/win32/README.txt +++ b/win32/README.txt @@ -63,9 +63,7 @@ CAIRO_FT: Enable the build of the hb-view tool, which makes use of Cairo, and GRAPHITE2: Enable the Graphite2 shaper, requires the SIL Graphite2 library. -ICU: Enables the build HarfBuzz-ICU, which is now the recommended layout engine - for ICU (International Components for Unicode), which deprecated ICU LE. - Requires the ICU libraries. +ICU: Enables the build of ICU Unicode functions. Requires the ICU libraries. UNISCRIBE: Enable Uniscribe platform shaper support. From 4cd0cd67914db1da10906e40335faea7dbec1d0a Mon Sep 17 00:00:00 2001 From: elmarb Date: Wed, 7 Dec 2016 11:50:27 +0100 Subject: [PATCH 0153/1326] NMake ICU option builds with builtin ICU (#375) --- win32/build-rules-msvc.mak | 13 ------------- win32/config-msvc.mak | 37 ++++++++++++++++++++----------------- win32/create-lists-msvc.mak | 13 ------------- win32/detectenv-msvc.mak | 4 +++- win32/generate-msvc.mak | 2 +- win32/info-msvc.mak | 12 +++++------- win32/install.mak | 4 ---- 7 files changed, 29 insertions(+), 56 deletions(-) diff --git a/win32/build-rules-msvc.mak b/win32/build-rules-msvc.mak index 03b383373..bfe02864a 100644 --- a/win32/build-rules-msvc.mak +++ b/win32/build-rules-msvc.mak @@ -23,11 +23,6 @@ $< $< << -{..\src\}.cc{$(CFG)\$(PLAT)\harfbuzz-icu\}.obj:: - $(CXX) $(CFLAGS) $(HB_LIB_CFLAGS) $(HB_ICU_CFLAGS) /Fo$(CFG)\$(PLAT)\harfbuzz-icu\ /c @<< -$< -<< - {..\util\}.cc{$(CFG)\$(PLAT)\util\}.obj:: $(CXX) $(CFLAGS) $(HB_DEFINES) $(HB_CFLAGS) /Fo$(CFG)\$(PLAT)\util\ /c @<< $< @@ -48,7 +43,6 @@ $< # Rules for building .lib files $(CFG)\$(PLAT)\harfbuzz.lib: $(HARFBUZZ_DLL_FILENAME).dll -$(CFG)\$(PLAT)\harfbuzz-icu.lib: $(HARFBUZZ_ICU_DLL_FILENAME).dll $(CFG)\$(PLAT)\harfbuzz-gobject.lib: $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll # Rules for linking DLLs @@ -64,12 +58,6 @@ $(harfbuzz_dll_OBJS) << @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 -$(HARFBUZZ_ICU_DLL_FILENAME).dll: $(CFG)\$(PLAT)\harfbuzz.lib $(harfbuzz_icu_OBJS) $(CFG)\$(PLAT)\harfbuzz-icu - link /DLL $(LDFLAGS) $(CFG)\$(PLAT)\harfbuzz.lib $(HB_ICU_DEP_LIBS) /implib:$(CFG)\$(PLAT)\harfbuzz-icu.lib -out:$@ @<< -$(harfbuzz_icu_OBJS) -<< - @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 - $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll: $(CFG)\$(PLAT)\harfbuzz.lib $(harfbuzz_gobject_OBJS) $(CFG)\$(PLAT)\harfbuzz-gobject link /DLL $(LDFLAGS) $(CFG)\$(PLAT)\harfbuzz.lib $(HB_GOBJECT_DEP_LIBS) /implib:$(CFG)\$(PLAT)\harfbuzz-gobject.lib -out:$@ @<< $(harfbuzz_gobject_OBJS) @@ -131,7 +119,6 @@ clean: @-del /f /q $(CFG)\$(PLAT)\*.obj @-if exist $(CFG)\$(PLAT)\util del /f /q $(CFG)\$(PLAT)\util\*.obj @-if exist $(CFG)\$(PLAT)\harfbuzz-gobject del /f /q $(CFG)\$(PLAT)\harfbuzz-gobject\*.obj - @-if exist $(CFG)\$(PLAT)\harfbuzz-icu del /f /q $(CFG)\$(PLAT)\harfbuzz-icu\*.obj @-del /f /q $(CFG)\$(PLAT)\harfbuzz\*.obj @-rmdir /s /q $(CFG)\$(PLAT) @-if exist $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h del $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak index d8b851d1e..ecbbe92fd 100644 --- a/win32/config-msvc.mak +++ b/win32/config-msvc.mak @@ -60,29 +60,12 @@ HB_TESTS_DEP_LIBS = $(HB_GLIB_LIBS) # Use libtool-style DLL names, if desired !if "$(LIBTOOL_DLL_NAME)" == "1" HARFBUZZ_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-0 -HARFBUZZ_ICU_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-icu-0 HARFBUZZ_GOBJECT_DLL_FILENAME = $(CFG)\$(PLAT)\libharfbuzz-gobject-0 !else HARFBUZZ_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-vs$(VSVER) -HARFBUZZ_ICU_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-icu-vs$(VSVER) HARFBUZZ_GOBJECT_DLL_FILENAME = $(CFG)\$(PLAT)\harfbuzz-gobject-vs$(VSVER) !endif -# Enable HarfBuzz-ICU, if desired -!if "$(ICU)" == "1" -HB_ICU_CFLAGS = -HB_LIBS = \ - $(HB_LIBS) \ - $(CFG)\$(PLAT)\harfbuzz-icu.lib - -# We don't want to re-define int8_t Visual Studio 2008, will cause build breakage -# as we define it in hb-common.h, and we ought to use the definitions there. -!if "$(VSVER)" == "9" -HB_ICU_CFLAGS = /DU_HAVE_INT8_T -!endif - -!endif - # Enable Introspection (enables HarfBuzz-Gobject as well) !if "$(INTROSPECTION)" == "1" GOBJECT = 1 @@ -181,6 +164,26 @@ HB_TESTS = \ $(CFG)\$(PLAT)\test-unicode.exe \ $(CFG)\$(PLAT)\test-version.exe +!elseif "$(ICU)" == "1" +# use ICU for Unicode functions +# and define some of the macros in GLib's msvc_recommended_pragmas.h +# to reduce some unneeded build-time warnings +HB_DEFINES = $(HB_DEFINES) /DHAVE_ICU=1 /DHAVE_ICU_BUILTIN=1 +HB_CFLAGS = \ + $(HB_CFLAGS) \ + /wd4244 \ + /D_CRT_SECURE_NO_WARNINGS \ + /D_CRT_NONSTDC_NO_WARNINGS + +# We don't want ICU to re-define int8_t in VS 2008, will cause build breakage +# as we define it in hb-common.h, and we ought to use the definitions there. +!if "$(VSVER)" == "9" +HB_CFLAGS = $(HB_CFLAGS) /DU_HAVE_INT8_T +!endif + +HB_SOURCES = $(HB_SOURCES) $(HB_ICU_sources) +HB_HEADERS = $(HB_HEADERS) $(HB_ICU_headers) +HB_DEP_LIBS = $(HB_DEP_LIBS) $(HB_ICU_DEP_LIBS) !else # If there is no GLib support, use the built-in UCDN # and define some of the macros in GLib's msvc_recommended_pragmas.h diff --git a/win32/create-lists-msvc.mak b/win32/create-lists-msvc.mak index 9b5574bf9..dbd2a579c 100644 --- a/win32/create-lists-msvc.mak +++ b/win32/create-lists-msvc.mak @@ -59,19 +59,6 @@ NULL= !endif !endif -# For HarfBuzz-ICU -!if "$(ICU)" == "1" - -!if [call create-lists.bat header hb_objs.mak harfbuzz_icu_OBJS] -!endif - -!if [for %c in ($(HB_ICU_sources)) do @if "%~xc" == ".cc" @call create-lists.bat file hb_objs.mak ^$(CFG)\^$(PLAT)\harfbuzz-icu\%~nc.obj] -!endif - -!if [call create-lists.bat footer hb_objs.mak] -!endif -!endif - # For the utility programs (GLib support is required) !if "$(GLIB)" == "1" diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak index 80a5eed7a..ca09793cb 100644 --- a/win32/detectenv-msvc.mak +++ b/win32/detectenv-msvc.mak @@ -110,7 +110,9 @@ VALID_CFGSET = TRUE # the resulting binaries !if "$(CFG)" == "release" CFLAGS_ADD = /MD /O2 /GL /MP -!if "$(VSVER)" != "9" +!if $(VSVER) > 9 && $(VSVER) < 14 +# Undocumented "enhance optimized debugging" switch. Became documented +# as "/Zo" in VS 2013 Update 3, and is turned on by default in VS 2015. CFLAGS_ADD = $(CFLAGS_ADD) /d2Zi+ !endif !else diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak index 57cfb6ecb..32214ebbf 100644 --- a/win32/generate-msvc.mak +++ b/win32/generate-msvc.mak @@ -22,5 +22,5 @@ $(HB_GOBJECT_ENUM_GENERATED_SOURCES): ..\src\hb-gobject-enums.h.tmpl ..\src\hb-g !endif # Create the build directories -$(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-icu $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util: +$(CFG)\$(PLAT)\harfbuzz $(CFG)\$(PLAT)\harfbuzz-gobject $(CFG)\$(PLAT)\util: @-md $@ diff --git a/win32/info-msvc.mak b/win32/info-msvc.mak index bbe631bd0..3ec11d4dc 100644 --- a/win32/info-msvc.mak +++ b/win32/info-msvc.mak @@ -11,6 +11,8 @@ BUILT_TOOLS = hb-shape.exe hb-ot-shape-closure.exe !if "$(CAIRO_FT)" == "1" BUILT_TOOLS = hb-view.exe $(BUILT_TOOLS) !endif +!elseif "$(ICU)" == "1" +UNICODE_IMPL = ICU !else UNICODE_IMPL = ucdn !endif @@ -31,10 +33,6 @@ INC_FEATURES = $(INC_FEATURES) Uniscribe INC_FEATURES = $(INC_FEATURES) DirectWrite !endif -!if "$(ICU)" == "1" -BUILT_LIBRARIES = $(BUILT_LIBRARIES) HarfBuzz-ICU -!endif - !if "$(GOBJECT)" == "1" BUILT_LIBRARIES = $(BUILT_LIBRARIES) HarfBuzz-GObject !endif @@ -101,20 +99,20 @@ help: @echo library. Enables the build of utility programs. @echo. @echo ICU: - @echo Enable the HarfBuzz-ICU layout library, requires the International + @echo Enable build with ICU Unicode functions, requires the International @echo Components for Unicode (ICU) libraries. @echo. @echo GOBJECT: @echo Enable the HarfBuzz-GObject library, also implies GLib2 support, @echo requires the GNOME GLib2 libraries and tools, notably the glib-mkenums - @echo tool script, which will require a PERL interpretor (use + @echo tool script, which will require a PERL interpreter (use @echo PERL=^$(PATH_TO_PERL_INTERPRETOR)) if it is not already in your PATH). @echo. @echo INTROSPECTION: @echo Enable the build of introspection files, also implies GObject/GLib2 support, @echo requires the GNOME gobject-introspection libraries and tools. You will need @echo to ensure the pkg-config (.pc) files can be found for GObject-2.0 and the - @echo Python interpretor (that was used to build the gobject-introsoection tools) + @echo Python interpreter (that was used to build the gobject-introspection tools) @echo can be found by setting PKG_CONFIG_PATH beforehand, and passing in PYTHON= @echo ^$(PATH_TO_PYTHON_INTERPRETOR) respectively, if python.exe is not already @echo in your PATH. diff --git a/win32/install.mak b/win32/install.mak index fa239eaac..e0a38e316 100644 --- a/win32/install.mak +++ b/win32/install.mak @@ -8,9 +8,6 @@ install: all @copy /b $(HARFBUZZ_DLL_FILENAME).dll $(PREFIX)\bin @copy /b $(HARFBUZZ_DLL_FILENAME).pdb $(PREFIX)\bin @copy /b $(CFG)\$(PLAT)\harfbuzz.lib $(PREFIX)\lib - @if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(HARFBUZZ_ICU_DLL_FILENAME).dll $(PREFIX)\bin - @if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(HARFBUZZ_ICU_DLL_FILENAME).pdb $(PREFIX)\bin - @if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll copy /b $(CFG)\$(PLAT)\harfbuzz-icu.lib $(PREFIX)\lib @if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll $(PREFIX)\bin @if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(HARFBUZZ_GOBJECT_DLL_FILENAME).pdb $(PREFIX)\bin @if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy /b $(CFG)\$(PLAT)\harfbuzz-gobject.lib $(PREFIX)\lib @@ -21,7 +18,6 @@ install: all @if exist $(CFG)\$(PLAT)\hb-shape.exe copy /b $(CFG)\$(PLAT)\hb-shape.exe $(PREFIX)\bin @if exist $(CFG)\$(PLAT)\hb-shape.exe copy /b $(CFG)\$(PLAT)\hb-shape.pdb $(PREFIX)\bin @for %h in ($(HB_ACTUAL_HEADERS)) do @copy %h $(PREFIX)\include\harfbuzz - @if exist $(HARFBUZZ_ICU_DLL_FILENAME).dll for %h in ($(HB_ICU_headers)) do @copy ..\src\%h $(PREFIX)\include\harfbuzz @if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll for %h in ($(HB_GOBJECT_headers)) do @copy ..\src\%h $(PREFIX)\include\harfbuzz @if exist $(HARFBUZZ_GOBJECT_DLL_FILENAME).dll copy $(CFG)\$(PLAT)\harfbuzz-gobject\hb-gobject-enums.h $(PREFIX)\include\harfbuzz @rem Copy the generated introspection files From 1e1825bf47aa29968f75a78305d4541ce2c9d40c Mon Sep 17 00:00:00 2001 From: ebraminio Date: Sat, 17 Dec 2016 10:30:40 +0330 Subject: [PATCH 0154/1326] [dwrite] Provide an experimental API for justification (#279) --- src/hb-directwrite.cc | 48 +++++++++++++++++++++++++++++++++++-------- src/hb-directwrite.h | 4 ++++ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index d26b29851..b5c1113b1 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -209,8 +209,8 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data data->fontFile->Release (); if (data->dwriteFactory) { if (data->fontFileLoader) - data->dwriteFactory->UnregisterFontFileLoader(data->fontFileLoader); - data->dwriteFactory->Release(); + data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); + data->dwriteFactory->Release (); } if (data->fontFileLoader) delete data->fontFileLoader; @@ -542,12 +542,13 @@ static inline uint32_t hb_uint32_swap (const uint32_t v) * shaper */ -hb_bool_t -_hb_directwrite_shape(hb_shape_plan_t *shape_plan, +static hb_bool_t +_hb_directwrite_shape_full(hb_shape_plan_t *shape_plan, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, - unsigned int num_features) + unsigned int num_features, + float lineWidth) { hb_face_t *face = font->face; hb_directwrite_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); @@ -728,9 +729,6 @@ retry_getglyphs: return false; } - // TODO: get lineWith from somewhere - float lineWidth = 0; - IDWriteTextAnalyzer1* analyzer1; analyzer->QueryInterface (&analyzer1); @@ -900,3 +898,37 @@ retry_getglyphs: /* Wow, done! */ return true; } + +hb_bool_t +_hb_directwrite_shape(hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) +{ + return _hb_directwrite_shape_full(shape_plan, font, buffer, + features, num_features, 0); +} + +/* + * Public [experimental] API + */ + +hb_bool_t +hb_shape_dwrite_experimental_width(hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features, + float width) +{ + static char *shapers = "directwrite"; + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, + &buffer->props, features, num_features, &shapers); + hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer, + features, num_features, width); + + if (res) + buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; + + return res; +} diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h index 0e1b4799d..0eb116f4c 100644 --- a/src/hb-directwrite.h +++ b/src/hb-directwrite.h @@ -29,6 +29,10 @@ HB_BEGIN_DECLS +HB_EXTERN hb_bool_t +hb_shape_dwrite_experimental_width(hb_font_t *font, hb_buffer_t *buffer, + const hb_feature_t *features, unsigned int num_features, float width); + HB_END_DECLS #endif /* HB_DIRECTWRITE_H */ From ad273881c597a95929ce3b84f63865f9d7dcdb7e Mon Sep 17 00:00:00 2001 From: "Volker H. Simonis" Date: Wed, 14 Dec 2016 18:56:17 +0100 Subject: [PATCH 0155/1326] Minor fixes to pacify Coverity code scan Fixes https://github.com/behdad/harfbuzz/pull/377 --- src/hb-ot-font.cc | 6 +++++- src/hb-ot-layout-gpos-table.hh | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index df01bc9fa..5be055d34 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -355,7 +355,11 @@ struct hb_ot_face_cmap_accelerator_t if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true); + if (!subtable) + { + subtable = cmap->find_subtable (3, 0); + if (subtable) symbol = true; + } /* Meh. */ if (!subtable) subtable = &OT::Null(OT::CmapSubtable); diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 5c9fc29ca..952fd60fe 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -690,7 +690,7 @@ struct PairPosFormat1 (this+coverage).add_coverage (c->input); unsigned int count = pairSet.len; for (unsigned int i = 0; i < count; i++) - (this+pairSet[i]).collect_glyphs (c, &valueFormat1); + (this+pairSet[i]).collect_glyphs (c, valueFormat); } inline const Coverage &get_coverage (void) const @@ -709,7 +709,7 @@ struct PairPosFormat1 skippy_iter.reset (buffer->idx, 1); if (!skippy_iter.next ()) return_trace (false); - return_trace ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx)); + return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -718,11 +718,11 @@ struct PairPosFormat1 if (!c->check_struct (this)) return_trace (false); - unsigned int len1 = valueFormat1.get_len (); - unsigned int len2 = valueFormat2.get_len (); + unsigned int len1 = valueFormat[0].get_len (); + unsigned int len2 = valueFormat[1].get_len (); PairSet::sanitize_closure_t closure = { this, - &valueFormat1, + valueFormat, len1, 1 + len1 + len2 }; @@ -735,10 +735,10 @@ struct PairPosFormat1 OffsetTo coverage; /* Offset to Coverage table--from * beginning of subtable */ - ValueFormat valueFormat1; /* Defines the types of data in + ValueFormat valueFormat[2]; /* [0] Defines the types of data in * ValueRecord1--for the first glyph * in the pair--may be zero (0) */ - ValueFormat valueFormat2; /* Defines the types of data in + /* [1] Defines the types of data in * ValueRecord2--for the second glyph * in the pair--may be zero (0) */ OffsetArrayOf From 1c98ff87c76536553e53c131e75aba33033ee3a0 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 30 Sep 2016 18:15:37 +0900 Subject: [PATCH 0156/1326] Support building with older glib versions It is desirable to be able to build against older versions of glib. fd7a245 changed the configure check to require glib > 2.38 for G_TEST_DIST. Before that, version 2.16 was required, but in fact, since aafe395, G_PASTE is being used, which was introduced in 2.19.1. And since 0ef179e2, hb-glib uses GBytes, which were introduced in 2.31.10. 2.19.1 is rather old, but 2.38 is rather new. For Firefox, building against 2.22 is still supported, although we could probably get away with bumping that to 2.28. Either way, GBytes is not available. Arguably, if you build against a glib that doesn't support GBytes, you're not going to use the hb_glib_blob_create function, so we hide the function when building against such a glib. As for G_TEST_DIST, when building against versions of glib that don't support it, we can fallback to the previous behavior, which, AIUI, was just making the test not work when building in a separate directory. --- configure.ac | 2 +- src/hb-glib.cc | 2 ++ src/hb-glib.h | 3 ++- test/api/test-ot-math.c | 4 ++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6948aa6ff..f985e1047 100644 --- a/configure.ac +++ b/configure.ac @@ -147,7 +147,7 @@ AC_ARG_WITH(glib, [Use glib @<:@default=auto@:>@])],, [with_glib=auto]) have_glib=false -GLIB_DEPS="glib-2.0 >= 2.38" +GLIB_DEPS="glib-2.0 >= 2.19.1" AC_SUBST(GLIB_DEPS) if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :) diff --git a/src/hb-glib.cc b/src/hb-glib.cc index e20352475..2b91b5b65 100644 --- a/src/hb-glib.cc +++ b/src/hb-glib.cc @@ -382,6 +382,7 @@ hb_glib_get_unicode_funcs (void) return const_cast (&_hb_glib_unicode_funcs); } +#if GLIB_CHECK_VERSION(2,31,10) /** * hb_glib_blob_create: * @@ -398,3 +399,4 @@ hb_glib_blob_create (GBytes *gbytes) g_bytes_ref (gbytes), (hb_destroy_func_t) g_bytes_unref); } +#endif diff --git a/src/hb-glib.h b/src/hb-glib.h index 12c3e3b3a..5f04183ba 100644 --- a/src/hb-glib.h +++ b/src/hb-glib.h @@ -46,9 +46,10 @@ hb_glib_script_from_script (hb_script_t script); HB_EXTERN hb_unicode_funcs_t * hb_glib_get_unicode_funcs (void); +#if GLIB_CHECK_VERSION(2,31,10) HB_EXTERN hb_blob_t * hb_glib_blob_create (GBytes *gbytes); - +#endif HB_END_DECLS diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 5f4ccb7fc..049656a03 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -54,7 +54,11 @@ cleanupFreeType (void) static void openFont(const char* fontFile) { +#if GLIB_CHECK_VERSION(2,37,2) gchar* path = g_test_build_filename(G_TEST_DIST, fontFile, NULL); +#else + gchar* path = g_strdup(fontFile); +#endif FT_Error ft_error; if ((ft_error = FT_New_Face (ft_library, path, 0, &ft_face))) { From 7ed71eb347c894c5b4b012bcca0816922c3052c2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 20 Dec 2016 15:01:16 -0600 Subject: [PATCH 0157/1326] Protect collect_glyphs() and closure() against malicious DDOS fonts Fixes https://github.com/behdad/harfbuzz/issues/363 --- src/hb-ot-layout-gsub-table.hh | 58 ++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 6658a2cd9..a81cd79c2 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -41,7 +41,10 @@ struct SingleSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + /* TODO Switch to range-based API to work around malicious fonts. + * https://github.com/behdad/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); if (c->glyphs->has (glyph_id)) c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); @@ -52,7 +55,10 @@ struct SingleSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + /* TODO Switch to range-based API to work around malicious fonts. + * https://github.com/behdad/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); c->input->add (glyph_id); c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); @@ -120,7 +126,11 @@ struct SingleSubstFormat2 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } @@ -130,7 +140,11 @@ struct SingleSubstFormat2 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); c->output->add (substitute[iter.get_coverage ()]); } @@ -321,7 +335,11 @@ struct MultipleSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = sequence.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+sequence[iter.get_coverage ()]).closure (c); } @@ -439,7 +457,11 @@ struct AlternateSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = alternateSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) { const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; unsigned int count = alt_set.len; @@ -453,7 +475,11 @@ struct AlternateSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = alternateSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; unsigned int count = alt_set.len; @@ -762,7 +788,11 @@ struct LigatureSubstFormat1 { TRACE_CLOSURE (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = ligatureSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+ligatureSet[iter.get_coverage ()]).closure (c); } @@ -772,7 +802,11 @@ struct LigatureSubstFormat1 { TRACE_COLLECT_GLYPHS (this); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + unsigned int count = ligatureSet.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ c->input->add (iter.get_glyph ()); (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); } @@ -923,7 +957,11 @@ struct ReverseChainSingleSubstFormat1 const ArrayOf &substitute = StructAfter > (lookahead); Coverage::Iter iter; - for (iter.init (this+coverage); iter.more (); iter.next ()) { + count = substitute.len; + for (iter.init (this+coverage); iter.more (); iter.next ()) + { + if (unlikely (iter.get_coverage () >= count)) + break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } From de14c19d14be90367a1231de56dd347e3f54931c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 20 Dec 2016 20:50:38 -0600 Subject: [PATCH 0158/1326] [fuzzer] Separate main() into a new file --- test/fuzzing/hb-fuzzer.hh | 4 ++++ test/fuzzing/main.cc | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/fuzzing/hb-fuzzer.hh create mode 100644 test/fuzzing/main.cc diff --git a/test/fuzzing/hb-fuzzer.hh b/test/fuzzing/hb-fuzzer.hh new file mode 100644 index 000000000..d0c617e09 --- /dev/null +++ b/test/fuzzing/hb-fuzzer.hh @@ -0,0 +1,4 @@ +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); diff --git a/test/fuzzing/main.cc b/test/fuzzing/main.cc new file mode 100644 index 000000000..4692f7b5f --- /dev/null +++ b/test/fuzzing/main.cc @@ -0,0 +1,21 @@ +#include "hb-fuzzer.hh" + +#include +#include +#include +#include + +std::string FileToString(const std::string &Path) { + /* TODO This silently passes if file does not exist. Fix it! */ + std::ifstream T(Path.c_str()); + return std::string((std::istreambuf_iterator(T)), + std::istreambuf_iterator()); +} + +int main(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + std::string s = FileToString(argv[i]); + std::cout << argv[i] << std::endl; + LLVMFuzzerTestOneInput((const unsigned char*)s.data(), s.size()); + } +} From a0688e8e7b58c156f5809c272b5884bfe75f68ae Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 20 Dec 2016 20:52:50 -0600 Subject: [PATCH 0159/1326] Ouch, finish previous change --- test/fuzzing/Makefile.am | 3 ++- test/fuzzing/hb-fuzzer.cc | 30 ++++-------------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am index 7b0eb9452..3ea8605bd 100644 --- a/test/fuzzing/Makefile.am +++ b/test/fuzzing/Makefile.am @@ -30,14 +30,15 @@ LDADD = \ $(NULL) hb_fuzzer_SOURCES = \ + hb-fuzzer.hh \ hb-fuzzer.cc \ + main.cc \ $(NULL) hb_fuzzer_LDADD = \ $(LDADD) \ $(NULL) hb_fuzzer_CPPFLAGS = \ $(AM_CPPFLAGS) \ - -DMAIN \ $(NULL) hb_fuzzer_DEPENDENCIES = \ lib \ diff --git a/test/fuzzing/hb-fuzzer.cc b/test/fuzzing/hb-fuzzer.cc index c9f15d831..79f322297 100644 --- a/test/fuzzing/hb-fuzzer.cc +++ b/test/fuzzing/hb-fuzzer.cc @@ -1,10 +1,10 @@ -#include -#include +#include "hb-fuzzer.hh" + #include #include -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ hb_blob_t *blob = hb_blob_create((const char *)data, size, HB_MEMORY_MODE_READONLY, NULL, NULL); hb_face_t *face = hb_face_create(blob, 0); @@ -50,25 +50,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { hb_blob_destroy(blob); return 0; } - -#ifdef MAIN -#include -#include -#include -#include - -std::string FileToString(const std::string &Path) { - /* TODO This silently passes if file does not exist. Fix it! */ - std::ifstream T(Path.c_str()); - return std::string((std::istreambuf_iterator(T)), - std::istreambuf_iterator()); -} - -int main(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - std::string s = FileToString(argv[i]); - std::cout << argv[i] << std::endl; - LLVMFuzzerTestOneInput((const unsigned char*)s.data(), s.size()); - } -} -#endif From eab418c5e6fa34b90133862cc8ce11e617ce08bf Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 21 Dec 2016 15:51:28 -0600 Subject: [PATCH 0160/1326] Avoid infinite loop in CoverageFormat2 iteration with bad fonts Fixes https://github.com/behdad/harfbuzz/issues/363 --- src/hb-ot-layout-common-private.hh | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 4c7714a8e..62ca7a348 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -731,8 +731,8 @@ struct CoverageFormat1 inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; inline bool more (void) { return i < c->glyphArray.len; } inline void next (void) { i++; } - inline uint16_t get_glyph (void) { return c->glyphArray[i]; } - inline uint16_t get_coverage (void) { return i; } + inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; } + inline unsigned int get_coverage (void) { return i; } private: const struct CoverageFormat1 *c; @@ -829,26 +829,33 @@ struct CoverageFormat2 public: /* Older compilers need this to be public. */ - struct Iter { - inline void init (const CoverageFormat2 &c_) { + struct Iter + { + inline void init (const CoverageFormat2 &c_) + { c = &c_; coverage = 0; i = 0; j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; } inline bool more (void) { return i < c->rangeRecord.len; } - inline void next (void) { - coverage++; - if (j == c->rangeRecord[i].end) { + inline void next (void) + { + if (j >= c->rangeRecord[i].end) + { i++; if (more ()) + { j = c->rangeRecord[i].start; + coverage = c->rangeRecord[i].value; + } return; } + coverage++; j++; } - inline uint16_t get_glyph (void) { return j; } - inline uint16_t get_coverage (void) { return coverage; } + inline hb_codepoint_t get_glyph (void) { return j; } + inline unsigned int get_coverage (void) { return coverage; } private: const struct CoverageFormat2 *c; @@ -957,14 +964,14 @@ struct Coverage default: break; } } - inline uint16_t get_glyph (void) { + inline hb_codepoint_t get_glyph (void) { switch (format) { case 1: return u.format1.get_glyph (); case 2: return u.format2.get_glyph (); default:return 0; } } - inline uint16_t get_coverage (void) { + inline unsigned int get_coverage (void) { switch (format) { case 1: return u.format1.get_coverage (); case 2: return u.format2.get_coverage (); From df98ce5fc8cf1dafd58c329975f07aafbeee3263 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 21 Dec 2016 19:27:30 -0600 Subject: [PATCH 0161/1326] Improve debug output with really deep nesting --- src/hb-private.hh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/hb-private.hh b/src/hb-private.hh index c45be6f2f..666af6260 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -689,17 +689,20 @@ _hb_debug_msg_va (const char *what, fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); if (indented) { -/* One may want to add ASCII version of these. See: - * https://bugs.freedesktop.org/show_bug.cgi?id=50970 */ #define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ #define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ #define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */ #define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ #define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */ - static const char bars[] = VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; + static const char bars[] = + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; fprintf (stderr, "%2u %s" VRBAR "%s", level, - bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars), (unsigned int) (sizeof (VBAR) - 1) * level), + bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); } else fprintf (stderr, " " VRBAR LBAR); From 4b4a1b9f235598b04ce9ae1f9670fc978ab7620d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 21 Dec 2016 23:10:43 -0600 Subject: [PATCH 0162/1326] Fix assert fail with contextual matching As discovered by libFuzzer / Chromium fuzzing. Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=659496 CC https://github.com/behdad/harfbuzz/issues/139 --- src/hb-ot-layout-gsubgpos-private.hh | 6 +++++- .../217a934cfe15c548b572c203dceb2befdf026462.ttf | Bin 0 -> 1384 bytes test/shaping/tests/fuzzed.tests | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index b90af9ca0..fd75c5425 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -1001,8 +1001,12 @@ static inline bool apply_lookup (hb_apply_context_t *c, end = int (end) + delta; if (end <= match_positions[idx]) { + /* End might end up being smaller than match_positions[idx] if the recursed + * lookup ended up removing many items, more than we have had matched. + * Just never rewind end back and get out of here. + * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */ + end = match_positions[idx]; /* There can't be any further changes. */ - assert (end == match_positions[idx]); break; } diff --git a/test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf b/test/shaping/fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf new file mode 100644 index 0000000000000000000000000000000000000000..12b91a09f9325bdb1c0c1935e35e5cd4892b04c3 GIT binary patch literal 1384 zcmb_c%}Z2K6#w1#=KIS*Ow3G18C;lBnrMN9i8%#A#@LsO^ffbn;Cwu0rm)@6s(+v$ zu-4(qrLJoc5z@*;T!cZna1mivLcV_IJ*SVo_i^u>-?_hg?m6e4Gf)5`s6fYLV(8K^ znsA(&9nRLo=+)$i_u?}^MJvEwB6)oyUOdI}yB&=-jNr;Uxi~ zA!T@*eS^g3h#PXoyh-0jh)0QIc_Wu`H3feV(+6BO3#GEvjwi&+vX7sZWr-yjn)n45 z6x{rDco3k>P&osL1uj4tMdL1f46_gJw_+jU8Kn*w%Ni2vNl_o!_?~9mRhno?mrx{CiaBm=Z*AY zdl$;uu@)GMI&N(mo(2gi(I2Z92?uwsm$&Sn~oaD=* zqme2nm9iC}T+0CDaz*2kItfq0a8gDygGX2ma?RgrFpHTfCo3@=O*KeR^2R=9$*Dcb zs=Q#7SaMf=eW^%4v`s2voZ4%i{J&3YR0}oIr*(F$4k*xoH+OIn2yfYMl;+Vf^ZVNVwQv!tK;(>5ENHq{Dz9#S eT?1+gPkDK>ySuBWucx=?yxWzgLVq7~*uMdwCB;|( literal 0 HcmV?d00001 diff --git a/test/shaping/tests/fuzzed.tests b/test/shaping/tests/fuzzed.tests index 7a5d395a9..771ac2b45 100644 --- a/test/shaping/tests/fuzzed.tests +++ b/test/shaping/tests/fuzzed.tests @@ -9,3 +9,4 @@ fonts/sha1sum/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf:--font-funcs=ot:U+004 fonts/sha1sum/3511ff5c1647150595846ac414c595cccac34f18.ttf:--font-funcs=ot:U+0041:[gid0=0+1000|gid512=0+1000|gid15104=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17872=0+1000|gid17961=0+1000|gid0=0+1000|gid992=0+1000|gid15616=0+1000|gid0=0+1000|gid14151=0+1000|gid20559=0+1000|gid20992=0+1000|gid5440=0+1000|gid256=0+1000|gid0=0+1000|gid10=0+1000|gid8960=0+1000|gid256=0+1000|gid1024=0+1000|gid1490=0+1000|gid0=0+1000|gid768=0+1000|gid4096=0+1000|gid256=0+1000|gid2216=0+1000|gid0=0+1000|gid256=0+1000|gid256=0+1000|gid0=0+1000|gid768=0+1000|gid10752=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53248=0+1000|gid256=0+1000|gid0=0+1000|gid512=0+1000|gid14848=0+1000|gid10793=0+1000|gid57344=0+1000|gid768=0+1000|gid18227=0+1000|gid20285=0+1000|gid20480=0+1000|gid0=0+1000|gid256=0+1000|gid0=0+1000|gid810=0+1000|gid0=0+1000|gid11004=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53289=0+1000|gid57344=0+1000|gid768=0+1000|gid15667=0+1000|gid71=0+1000|gid0=0+1000|gid20559=0+1000|gid21248=0+1000|gid256=0+1000|gid0=0+1000|gid2816=0+1000|gid2776=0+1000|gid0=0+1000|gid51516=0+1000|gid0=0+1000|gid32=0+1000|gid26209=0+1000|gid28005=0+1000|gid65249=0+1000|gid29690=0+1000|gid0=0+1000|gid51548=0+1000|gid0=0+1000|gid2454=0+1000|gid28783=0+1000|gid29556=0+1000|gid1291=0+1000|gid3458=0+1000|gid80=0+1000|gid0=0+1000|gid2804=0+1000|gid210=0+1000|gid28786=0+1000|gid25968=0+1000|gid45763=0+1000|gid50546=0+1000|gid0=0+1000|gid59136=0+1000|gid0=0+1000|gid38144=0+1000|gid256=0+1000|gid0=0+1000|gid2560=0+1000|gid30208=0+1000|gid52224=0+1000|gid580=0+1000|gid17996=0+1000|gid21504=0+1000|gid6734=0+1000|gid108=0+1000|gid116=0+1000|gid24846=0+1000|gid1024=0+1000|gid0=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid0=0+1000|gid8704=0+1000|gid1345=0+1000|gid23109=0+1000|gid8192=0+1000|gid10823=0+1000|gid21076=0+1000|gid8192=0+1000|gid12877=0+1000|gid20300=0+1000|gid8192=0+1000|gid6738=0+1000|gid20301=0+1000|gid8192=0+1000|gid16980=0+1000|gid21067=0+1000|gid8251=0+1000|gid18944=0+1000|gid255=0+1000|gid65280=0+1000|gid15360=0+1000|gid256=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid768=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid768=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid1024=0+1000|gid12=0+1000|gid65280=0+1000|gid256=0+1000|gid1280=0+1000|gid255=0+1000|gid65280=0+1000|gid256=0+1000|gid1536=0+1000|gid1899=0+1000|gid25970=0+1000|gid110=0+1000|gid11264=0+1000|gid27502=0+1000|gid29285=0+1000|gid12907=0+1000|gid25974=0+1000|gid28160=0+1000|gid14443=0+1000|gid25970=0+1000|gid28288=0+1000|gid3=0+1000|gid118=0+1000|gid18259=0+1000|gid21826=0+1000|gid45716=0+1000|gid46369=0+1000|gid0=0+1000|gid0=0+1000|gid1=0+1000|gid16=0+1000|gid17=0+1000|gid256=0+1000|gid4=0+1000|gid16=0+1000|gid18244=0+1000|gid17734=0+1000|gid28=0+1000|gid12=0+1000|gid0=0+1000|gid284=0+1000|gid0=0+1000|gid28=0+1000|gid18256=0+1000|gid20307=0+1000|gid45114=0+1000|gid47616=0+1000|gid226=0+1000|gid10296=0+1000|gid0=0+1000|gid57927=0+1000|gid1=0+1000|gid0=0+1000|gid0=0+1000|gid21248=0+1000|gid5440=0+1000|gid256=0+1000|gid0=0+1000|gid10=0+1000|gid768=0+1000|gid256=0+1000|gid1024=0+1000|gid512=0+1000|gid0=0+1000|gid297=0+1000|gid16=0+1000|gid24833=0+1000|gid28774=0+1000|gid10794=0+1000|gid2304=0+1000|gid29=0+1000|gid32=0+1000|gid42=0+1000|gid64515=0+1000|gid42=0+1000|gid42=0+1000|gid64525=0+1000|gid20551=0+1000|gid17477=0+1000|gid18128=0+1000|gid10720=0+1000|gid3=0+1000|gid61=0+1000|gid3408=0+1000|gid18244=0+1000|gid17734=0+1000|gid53289=0+1000|gid57344=0+1000|gid768=0+1000|gid15616=0+1000|gid512=0+1000|gid55=0+1000|gid10576=0+1000|gid20307=0+1000|gid0=0+1000|gid255=0+1000|gid56063=0+1000|gid53504=0+1000|gid42=0+1000|gid42=0+1000|gid64525=0+1000|gid12288=0+1000|gid18176=0+1000|gid80=0+1000|gid20307=0+1000|gid1=0+1000|gid0=0+1000|gid62=0+1000] fonts/sha1sum/fab39d60d758cb586db5a504f218442cd1395725.ttf:--font-funcs=ot:U+0041,U+0041:[gid0=0+1000|gid0=1+1000] fonts/sha1sum/205edd09bd3d141cc9580f650109556cc28b22cb.ttf:--font-funcs=ot:U+0041:[gid0=0+1000] +fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf:--font-funcs=ot:U+0061,U+0061,U+0061:[] From 1a0f4aa6dfee69236b422f7c8825eff940f45c19 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 22 Dec 2016 13:33:54 -0600 Subject: [PATCH 0163/1326] Revert "Synthesize GDEF glyph class for any glyph that does not have one in GDEF" This reverts commit 69f9fbc4200442a35484d3c790ae8f4979be5d60. See https://github.com/behdad/harfbuzz/issues/347#issuecomment-268873401 Fixes https://github.com/behdad/harfbuzz/issues/347 --- src/hb-ot-layout-gsub-table.hh | 22 ++-------------------- src/hb-ot-shape.cc | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index a81cd79c2..66fcb3f3a 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1321,28 +1321,10 @@ GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - unsigned int props = gdef.get_glyph_props (info[i].codepoint); - if (!props) - { - /* Never mark default-ignorables as marks. - * They won't get in the way of lookups anyway, - * but having them as mark will cause them to be skipped - * over if the lookup-flag says so, but at least for the - * Mongolian variation selectors, looks like Uniscribe - * marks them as non-mark. Some Mongolian fonts without - * GDEF rely on this. Another notable character that - * this applies to is COMBINING GRAPHEME JOINER. */ - props = (_hb_glyph_info_get_general_category (&info[i]) != - HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || - _hb_glyph_info_is_default_ignorable (&info[i])) ? - HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : - HB_OT_LAYOUT_GLYPH_PROPS_MARK; - } - _hb_glyph_info_set_glyph_props (&info[i], props); - _hb_glyph_info_clear_lig_props (&info[i]); + _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); + _hb_glyph_info_clear_lig_props (&buffer->info[i]); buffer->info[i].syllable() = 0; } } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 987279878..cf916cc82 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -529,6 +529,32 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer) buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; } +static inline void +hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) +{ + unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + for (unsigned int i = 0; i < count; i++) + { + hb_ot_layout_glyph_props_flags_t klass; + + /* Never mark default-ignorables as marks. + * They won't get in the way of lookups anyway, + * but having them as mark will cause them to be skipped + * over if the lookup-flag says so, but at least for the + * Mongolian variation selectors, looks like Uniscribe + * marks them as non-mark. Some Mongolian fonts without + * GDEF rely on this. Another notable character that + * this applies to is COMBINING GRAPHEME JOINER. */ + klass = (_hb_glyph_info_get_general_category (&info[i]) != + HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || + _hb_glyph_info_is_default_ignorable (&info[i])) ? + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : + HB_OT_LAYOUT_GLYPH_PROPS_MARK; + _hb_glyph_info_set_glyph_props (&info[i], klass); + } +} + static inline void hb_ot_substitute_default (hb_ot_shape_context_t *c) { @@ -560,6 +586,9 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c) hb_ot_layout_substitute_start (c->font, buffer); + if (!hb_ot_layout_has_glyph_classes (c->face)) + hb_synthesize_glyph_classes (c); + c->plan->substitute (c->font, buffer); return; From e2b878055bb1c0b84e1f7cfbf3d3f80bfc6811ea Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 22 Dec 2016 14:40:19 -0600 Subject: [PATCH 0164/1326] Disable OTL processing for Hebrew if GPOS doesn't have Hebrew subtable New approach to fix this: https://github.com/behdad/harfbuzz/commit/69f9fbc4200442a35484d3c790ae8f4979be5d60 Previous approach was reverted as it was too broad. See context: https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368 With U+05E9,U+05B8,U+05C1,U+05DC and Arial Unicode, we now (correctly) disable GDEF and GPOS, so we get results very close to Uniscribe, but slightly different since our fallback position logic is not exactly the same: Before: [gid1166=3+991|gid1142=0+737|gid5798=0+1434] After: [gid1166=3+991|gid1142=0@402,-26+0|gid5798=0+1434] Uniscribe: [gid1166=3+991|gid1142=0@348,0+0|gid5798=0+1434] --- src/hb-ot-shape-complex-arabic.cc | 1 + src/hb-ot-shape-complex-default.cc | 1 + src/hb-ot-shape-complex-hangul.cc | 1 + src/hb-ot-shape-complex-hebrew.cc | 13 +++++++++++++ src/hb-ot-shape-complex-indic.cc | 1 + src/hb-ot-shape-complex-myanmar.cc | 2 ++ src/hb-ot-shape-complex-private.hh | 8 ++++++++ src/hb-ot-shape-complex-thai.cc | 1 + src/hb-ot-shape-complex-tibetan.cc | 1 + src/hb-ot-shape-complex-use.cc | 1 + src/hb-ot-shape.cc | 29 ++++++++++++++++------------- 11 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 4da899055..56ec5cd65 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -618,6 +618,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = NULL, /* decompose */ NULL, /* compose */ setup_masks_arabic, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-default.cc b/src/hb-ot-shape-complex-default.cc index be60e56fe..42830ab61 100644 --- a/src/hb-ot-shape-complex-default.cc +++ b/src/hb-ot-shape-complex-default.cc @@ -40,6 +40,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc index 5f4d98b70..eb95a28c0 100644 --- a/src/hb-ot-shape-complex-hangul.cc +++ b/src/hb-ot-shape-complex-hangul.cc @@ -419,6 +419,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = NULL, /* decompose */ NULL, /* compose */ setup_masks_hangul, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index 32159002e..96f249461 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -154,6 +154,18 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c, return found; } +static bool +disable_otl_hebrew (const hb_ot_shape_plan_t *plan) +{ + /* For Hebrew shaper, use fallback if GPOS does not have 'hebr' + * script. This matches Uniscribe better, and makes fonts like + * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work. + * See: + * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368 + */ + return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r'); +} + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = { @@ -168,6 +180,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = NULL, /* decompose */ compose_hebrew, NULL, /* setup_masks */ + disable_otl_hebrew, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 94556f654..ec6e82c4f 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1819,6 +1819,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = decompose_indic, compose_indic, setup_masks_indic, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 577d790c7..bb68622e2 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -521,6 +521,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; @@ -538,6 +539,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = NULL, /* decompose */ NULL, /* compose */ setup_masks_myanmar, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index fb0c70406..39572dfe0 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -146,6 +146,14 @@ struct hb_ot_complex_shaper_t hb_buffer_t *buffer, hb_font_t *font); + /* disable_otl() + * Called during shape(). + * If set and returns true, GDEF/GSUB/GPOS of the font are ignored + * and fallback operations used. + * May be NULL. + */ + bool (*disable_otl) (const hb_ot_shape_plan_t *plan); + hb_ot_shape_zero_width_marks_type_t zero_width_marks; bool fallback_position; diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index 4322b0d1d..e6f80f59e 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -376,6 +376,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-tibetan.cc b/src/hb-ot-shape-complex-tibetan.cc index a77b531da..aadf59f5a 100644 --- a/src/hb-ot-shape-complex-tibetan.cc +++ b/src/hb-ot-shape-complex-tibetan.cc @@ -57,6 +57,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = NULL, /* decompose */ NULL, /* compose */ NULL, /* setup_masks */ + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 045ead52f..13c7ab3bc 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -585,6 +585,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = NULL, /* decompose */ compose_use, setup_masks_use, + NULL, /* disable_otl */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index cf916cc82..ddd6662e8 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -218,6 +218,8 @@ struct hb_ot_shape_context_t unsigned int num_user_features; /* Transient stuff */ + bool fallback_positioning; + bool fallback_glyph_classes; hb_direction_t target_direction; }; @@ -571,7 +573,7 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) hb_ot_shape_setup_masks (c); /* This is unfortunate to go here, but necessary... */ - if (!hb_ot_layout_has_positioning (c->face)) + if (c->fallback_positioning) _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer); hb_ot_map_glyphs_fast (buffer); @@ -667,14 +669,12 @@ hb_ot_position_default (hb_ot_shape_context_t *c) _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer); } -static inline bool +static inline void hb_ot_position_complex (hb_ot_shape_context_t *c) { hb_ot_layout_position_start (c->font, c->buffer); - bool ret = false; unsigned int count = c->buffer->len; - bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face); /* If the font has no GPOS, AND, no fallback positioning will * happen, AND, direction is forward, then when zeroing mark @@ -685,8 +685,9 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) * If fallback positinoing happens or GPOS is present, we don't * care. */ - bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position || - HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)); + bool adjust_offsets_when_zeroing = c->fallback_positioning && + !c->plan->shaper->fallback_position && + HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); switch (c->plan->shaper->zero_width_marks) { @@ -700,7 +701,7 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) break; } - if (has_positioning) + if (likely (!c->fallback_positioning)) { hb_glyph_info_t *info = c->buffer->info; hb_glyph_position_t *pos = c->buffer->pos; @@ -723,7 +724,6 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) &pos[i].x_offset, &pos[i].y_offset); - ret = true; } switch (c->plan->shaper->zero_width_marks) @@ -742,8 +742,6 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c); hb_ot_layout_position_finish_offsets (c->font, c->buffer); - - return ret; } static inline void @@ -753,9 +751,9 @@ hb_ot_position (hb_ot_shape_context_t *c) hb_ot_position_default (c); - hb_bool_t fallback = !hb_ot_position_complex (c); + hb_ot_position_complex (c); - if (fallback && c->plan->shaper->fallback_position) + if (c->fallback_positioning && c->plan->shaper->fallback_position) _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) @@ -763,7 +761,7 @@ hb_ot_position (hb_ot_shape_context_t *c) /* Visual fallback goes here. */ - if (fallback) + if (c->fallback_positioning) _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); _hb_buffer_deallocate_gsubgpos_vars (c->buffer); @@ -783,6 +781,11 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) (unsigned) HB_BUFFER_MAX_LEN_MIN); } + bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan); + //c->fallback_substitute = disable_otl || !hb_ot_layout_has_substitution (c->face); + c->fallback_positioning = disable_otl || !hb_ot_layout_has_positioning (c->face); + c->fallback_glyph_classes = disable_otl || !hb_ot_layout_has_glyph_classes (c->face); + /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; From 7d1c5d8281b05a5c178ea3ae048b0062145968aa Mon Sep 17 00:00:00 2001 From: nvelinov Date: Sat, 24 Dec 2016 02:46:37 +0100 Subject: [PATCH 0165/1326] Compilation Error for ASSERT_STATIC on Some Compilers (#380) * this pointer in type definitions is not interpreted as a constant. This rule is not enforced strictly by all compilers, but the Green Hills Software compiler will regard this as an error. * Merging branches for the DEFINE_SIZE_UNION macro Adding check for the existence of static_size field in the tested member. --- src/hb-open-type-private.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 5b7ff337e..2cc1fb20d 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -105,7 +105,7 @@ static inline Type& StructAfter(TObject &X) inline unsigned int get_size (void) const { return (size); } #define DEFINE_SIZE_UNION(size, _member) \ - DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \ + DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \ static const unsigned int min_size = (size) #define DEFINE_SIZE_MIN(size) \ From 3cc48a46b56be06e6734aaabf37a4b521606380c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Dec 2016 13:10:31 -0500 Subject: [PATCH 0166/1326] [indix] Comment --- src/hb-ot-shape-complex-indic.cc | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index ec6e82c4f..54fbfff52 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1713,33 +1713,52 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, switch (ab) { /* Don't decompose these. */ - case 0x0931u : return false; - case 0x0B94u : return false; + case 0x0931u : return false; /* DEVANAGARI LETTER RRA */ + case 0x0B94u : return false; /* TAMIL LETTER AU */ /* * Decompose split matras that don't have Unicode decompositions. */ + /* Tibetan */ case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true; case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true; + + /* Khmer */ case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true; case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true; case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true; case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true; case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true; + + /* Limbu */ case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; + + /* Balinese */ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; + + /* Chakma */ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + #if 0 + /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ /* case 0x0AC9u : return false; */ + + /* Oriya */ case 0x0B57u : *a = no decomp, -> RIGHT; return true; + + /* Lepcha */ case 0x1C29u : *a = no decomp, -> LEFT; return true; + + /* Javanese */ case 0xA9C0u : *a = no decomp, -> RIGHT; return true; - case 0x111BuF : *a = no decomp, -> ABOVE; return true; + + /* Sharada */ + case 0x111BFu : *a = no decomp, -> ABOVE; return true; #endif } From 805f76fc002d703acfcc4c5727f0b4d1baecefaa Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Dec 2016 14:11:59 -0500 Subject: [PATCH 0167/1326] [indic] Remove redundant Chakma decomposition rule This was not used BTW since Chakma doesn't go through Indic shaper anymore. See: https://github.com/behdad/harfbuzz/issues/381 https://github.com/behdad/harfbuzz/issues/382 --- src/hb-ot-shape-complex-indic.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 54fbfff52..36fa0147d 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1739,10 +1739,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, /* Balinese */ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - /* Chakma */ - case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; - case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; - #if 0 /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ From c4ca49d55b49c65e04f0b2acecacd6a5c70978f4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Dec 2016 14:52:08 -0500 Subject: [PATCH 0168/1326] Revert "[indic] Remove redundant Chakma decomposition rule" This reverts commit 805f76fc002d703acfcc4c5727f0b4d1baecefaa. Need to investigate why having this rule (with the reversed order) fixes decomposition as reported by punchcutter: https://github.com/behdad/harfbuzz/issues/381#issuecomment-269237796 --- src/hb-ot-shape-complex-indic.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 36fa0147d..54fbfff52 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1739,6 +1739,10 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, /* Balinese */ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; + /* Chakma */ + case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; + case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + #if 0 /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ From 49ba698124399373cea000d08e0e9fe5fc2396e8 Mon Sep 17 00:00:00 2001 From: jfkthame Date: Wed, 28 Dec 2016 18:00:51 +0000 Subject: [PATCH 0169/1326] [use] Special-case Chakma split-vowel decomp in the USE shaper. (#383) --- src/hb-ot-shape-complex-use.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 13c7ab3bc..af6870686 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -558,6 +558,25 @@ reorder (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); } +static bool +decompose_use (const hb_ot_shape_normalize_context_t *c, + hb_codepoint_t ab, + hb_codepoint_t *a, + hb_codepoint_t *b) +{ + switch (ab) + { + /* Chakma: + * Special case where the Unicode decomp gives matras in the wrong order + * for cluster validation. + */ + case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; + case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + } + + return (bool) c->unicode->decompose (ab, a, b); +} + static bool compose_use (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t a, @@ -582,7 +601,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = NULL, /* preprocess_text */ NULL, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, - NULL, /* decompose */ + decompose_use, compose_use, setup_masks_use, NULL, /* disable_otl */ From e678b537f77954615721abd65fef28854f95dc5d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 26 Dec 2016 14:11:59 -0500 Subject: [PATCH 0170/1326] [indic] Remove Chakma decomposition rule from Indic shaper This is now added to USE: https://github.com/behdad/harfbuzz/pull/383 See: https://github.com/behdad/harfbuzz/issues/381 https://github.com/behdad/harfbuzz/issues/382 --- src/hb-ot-shape-complex-indic.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 54fbfff52..36fa0147d 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1739,10 +1739,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, /* Balinese */ case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - /* Chakma */ - case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; - case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; - #if 0 /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ From f6ba63b2e8eb577385f70758efdd3b8408c8a9cb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Dec 2016 13:45:32 -0500 Subject: [PATCH 0171/1326] Port decompositions from Indic to USE shaper Part of https://github.com/behdad/harfbuzz/issues/382 --- src/hb-ot-shape-complex-indic.cc | 16 ---------------- src/hb-ot-shape-complex-use.cc | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 36fa0147d..19aca56a6 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1732,13 +1732,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true; case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true; - /* Limbu */ - case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; - case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; - - /* Balinese */ - case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - #if 0 /* Gujarati */ /* This one has no decomposition in Unicode, but needs no decomposition either. */ @@ -1746,15 +1739,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, /* Oriya */ case 0x0B57u : *a = no decomp, -> RIGHT; return true; - - /* Lepcha */ - case 0x1C29u : *a = no decomp, -> LEFT; return true; - - /* Javanese */ - case 0xA9C0u : *a = no decomp, -> RIGHT; return true; - - /* Sharada */ - case 0x111BFu : *a = no decomp, -> ABOVE; return true; #endif } diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index af6870686..5b19d5d74 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -572,6 +572,28 @@ decompose_use (const hb_ot_shape_normalize_context_t *c, */ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; + + /* + * Decompose split matras that don't have Unicode decompositions. + */ + + /* Limbu */ + case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; + case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; + + /* Balinese */ + case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; + +#if 0 + /* Lepcha */ + case 0x1C29u : *a = no decomp, -> LEFT; return true; + + /* Javanese */ + case 0xA9C0u : *a = no decomp, -> RIGHT; return true; + + /* Sharada */ + case 0x111BFu : *a = no decomp, -> ABOVE; return true; +#endif } return (bool) c->unicode->decompose (ab, a, b); From 6cff75394192a1ab0dda82981752ade532838333 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Dec 2016 13:46:21 -0500 Subject: [PATCH 0172/1326] Remove Tibetan decomposition rules from Indic shaper The decomposition is very obscure and unlikely to help any fonts. Just remove it since Uniscribe probably doesn't do this either. Fixes https://github.com/behdad/harfbuzz/issues/382 --- src/hb-ot-shape-complex-indic.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 19aca56a6..b48fb561c 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1721,10 +1721,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, * Decompose split matras that don't have Unicode decompositions. */ - /* Tibetan */ - case 0x0F77u : *a = 0x0FB2u; *b= 0x0F81u; return true; - case 0x0F79u : *a = 0x0FB3u; *b= 0x0F81u; return true; - /* Khmer */ case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true; case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true; From e053ccc5bb7268fe5900dd364d906638c58b2908 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Dec 2016 15:51:57 -0500 Subject: [PATCH 0173/1326] Remove Android.mk Android uses its own file these days and third-party developers should be using the autotools-based system against Android NDK. --- Android.mk | 107 ---------------------------------------------------- Makefile.am | 1 - 2 files changed, 108 deletions(-) delete mode 100644 Android.mk diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 654f0e0fc..000000000 --- a/Android.mk +++ /dev/null @@ -1,107 +0,0 @@ -## -## Copyright (C) 2012 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. -## - -############################################################# -# Note: -# -# This file is used to build HarfBuzz within the Android -# platform itself. If you need to compile HarfBuzz to -# ship with your Android NDK app, you can use the autotools -# build system to do so. To do that you need to install a -# "standalone" toolchain with the NDK, eg: -# -# ndk/build/tools/make-standalone-toolchain.sh \ -# --platform=android-18 \ -# --install-dir=/prefix -# -# Set PLATFORM_PREFIX eng var to that prefix and make sure -# the cross-compile tools from PLATFORM_PREFIX are in path. -# Configure and install HarfBuzz: -# -# ./configure --host=arm-linux-androideabi \ -# --prefix=$PLATFORM_PREFIX \ -# --enable-static \ -# --with-freetype \ -# PKG_CONFIG_LIBDIR=$PLATFORM_PREFIX/lib/pkgconfig -# make install -# -# You can first build FreeType the same way: -# -# ./configure --host=arm-linux-androideabi \ -# --prefix=$PLATFORM_PREFIX \ -# --enable-static \ -# --without-png \ -# PKG_CONFIG_LIBDIR=$PLATFORM_PREFIX/lib/pkgconfig -# make install -# - -LOCAL_PATH:= $(call my-dir) - -HARFBUZZ_SRC_FILES = \ - src/hb-blob.cc \ - src/hb-buffer-serialize.cc \ - src/hb-buffer.cc \ - src/hb-common.cc \ - src/hb-face.cc \ - src/hb-font.cc \ - src/hb-ot-tag.cc \ - src/hb-set.cc \ - src/hb-shape.cc \ - src/hb-shape-plan.cc \ - src/hb-shaper.cc \ - src/hb-unicode.cc \ - src/hb-warning.cc \ - src/hb-ot-font.cc \ - src/hb-ot-layout.cc \ - src/hb-ot-map.cc \ - src/hb-ot-shape.cc \ - src/hb-ot-shape-complex-arabic.cc \ - src/hb-ot-shape-complex-default.cc \ - src/hb-ot-shape-complex-hangul.cc \ - src/hb-ot-shape-complex-hebrew.cc \ - src/hb-ot-shape-complex-indic.cc \ - src/hb-ot-shape-complex-indic-table.cc \ - src/hb-ot-shape-complex-myanmar.cc \ - src/hb-ot-shape-complex-thai.cc \ - src/hb-ot-shape-complex-tibetan.cc \ - src/hb-ot-shape-complex-use.cc \ - src/hb-ot-shape-complex-use-table.cc \ - src/hb-ot-shape-normalize.cc \ - src/hb-ot-shape-fallback.cc \ - $(NULL) - -############################################################# -# build the harfbuzz shared library -# -include $(CLEAR_VARS) -LOCAL_ARM_MODE := arm -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES:= \ - $(HARFBUZZ_SRC_FILES) \ - src/hb-icu.cc -LOCAL_CPP_EXTENSION := .cc -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libicuuc \ - libicui18n \ - libutils \ - liblog -LOCAL_C_INCLUDES += \ - $(LOCAL_PATH)/src -LOCAL_CFLAGS += -DHB_NO_MT -DHAVE_OT -DHAVE_ICU -DHAVE_ICU_BUILTIN \ - -Wno-unused-parameter -Wno-missing-field-initializers -LOCAL_MODULE:= libharfbuzz_ng -include $(BUILD_SHARED_LIBRARY) diff --git a/Makefile.am b/Makefile.am index d56a151a3..8dc8a4b93 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,6 @@ SUBDIRS = src util test docs win32 EXTRA_DIST = \ autogen.sh \ harfbuzz.doap \ - Android.mk \ README.python \ BUILD.md \ $(NULL) From ae00af4a47587308969dfaf7baa93164d7842710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Wang?= Date: Tue, 3 Jan 2017 05:55:09 +0100 Subject: [PATCH 0174/1326] Move math-specific code from hb-ot-layout to hb-ot-math #235 (#384) --- src/Makefile.sources | 1 + src/hb-ot-layout.cc | 244 -------------------------------------- src/hb-ot-math.cc | 272 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 273 insertions(+), 244 deletions(-) create mode 100644 src/hb-ot-math.cc diff --git a/src/Makefile.sources b/src/Makefile.sources index 166793aa4..e72759842 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -80,6 +80,7 @@ HB_OT_sources = \ hb-ot-layout-private.hh \ hb-ot-map.cc \ hb-ot-map-private.hh \ + hb-ot-math.cc \ hb-ot-shape.cc \ hb-ot-shape-complex-arabic.cc \ hb-ot-shape-complex-arabic-fallback.hh \ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 345d5e695..145ec7638 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -35,7 +35,6 @@ #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-jstf-table.hh" -#include "hb-ot-layout-math-table.hh" #include "hb-ot-map-private.hh" @@ -205,31 +204,6 @@ _get_gpos (hb_face_t *face) if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS); return *hb_ot_layout_from_face (face)->gpos; } -static inline const OT::MATH& -_get_math (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); - - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - -retry: - const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); - - if (unlikely (!math)) - { - hb_blob_t *blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); - math = OT::Sanitizer::lock_instance (blob); - if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) - { - hb_blob_destroy (blob); - goto retry; - } - layout->math_blob = blob; - } - - return *math; -} - /* * GDEF @@ -1255,221 +1229,3 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, { apply_string (c, lookup, accel); } - - -/* - * MATH - */ -/* TODO Move this to hb-ot-math.cc and separate it from hb_ot_layout_t. */ - -/** - * hb_ot_math_has_data: - * @face: #hb_face_t to test - * - * This function allows to verify the presence of an OpenType MATH table on the - * face. If so, such a table will be loaded into memory and sanitized. You can - * then safely call other functions for math layout and shaping. - * - * Return value: #TRUE if face has a MATH table and #FALSE otherwise - * - * Since: 1.3.3 - **/ -hb_bool_t -hb_ot_math_has_data (hb_face_t *face) -{ - return &_get_math (face) != &OT::Null(OT::MATH); -} - -/** - * hb_ot_math_get_constant: - * @font: #hb_font_t from which to retrieve the value - * @constant: #hb_ot_math_constant_t the constant to retrieve - * - * This function returns the requested math constants as a #hb_position_t. - * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, - * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or - * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is - * actually an integer between 0 and 100 representing that percentage. - * - * Return value: the requested constant or 0 - * - * Since: 1.3.3 - **/ -hb_position_t -hb_ot_math_get_constant (hb_font_t *font, - hb_ot_math_constant_t constant) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_constant(constant, font); -} - -/** - * hb_ot_math_get_glyph_italics_correction: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value - * - * Return value: the italics correction of the glyph or 0 - * - * Since: 1.3.3 - **/ -hb_position_t -hb_ot_math_get_glyph_italics_correction (hb_font_t *font, - hb_codepoint_t glyph) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_glyph_info().get_italics_correction (glyph, font); -} - -/** - * hb_ot_math_get_glyph_top_accent_attachment: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value - * - * Return value: the top accent attachment of the glyph or 0 - * - * Since: 1.3.3 - **/ -hb_position_t -hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, - hb_codepoint_t glyph) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); -} - -/** - * hb_ot_math_is_glyph_extended_shape: - * @font: a #hb_font_t to test - * @glyph: a glyph index to test - * - * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise - * - * Since: 1.3.3 - **/ -hb_bool_t -hb_ot_math_is_glyph_extended_shape (hb_face_t *face, - hb_codepoint_t glyph) -{ - const OT::MATH &math = _get_math (face); - return math.get_math_glyph_info().is_extended_shape (glyph); -} - -/** - * hb_ot_math_get_glyph_kerning: - * @font: #hb_font_t from which to retrieve the value - * @glyph: glyph index from which to retrieve the value - * @kern: the #hb_ot_math_kern_t from which to retrieve the value - * @correction_height: the correction height to use to determine the kerning. - * - * This function tries to retrieve the MathKern table for the specified font, - * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the - * MathKern table to find one value that is greater or equal to specified - * correction_height. If one is found the corresponding value from the list of - * kerns is returned and otherwise the last kern value is returned. - * - * Return value: requested kerning or 0 - * - * Since: 1.3.3 - **/ -hb_position_t -hb_ot_math_get_glyph_kerning (hb_font_t *font, - hb_codepoint_t glyph, - hb_ot_math_kern_t kern, - hb_position_t correction_height) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); -} - -/** - * hb_ot_math_get_glyph_variants: - * @font: #hb_font_t from which to retrieve the values - * @glyph: index of the glyph to stretch - * @direction: direction of the stretching - * @start_offset: offset of the first variant to retrieve - * @variants_count: maximum number of variants to retrieve after start_offset - * (IN) and actual number of variants retrieved (OUT) - * @variants: array of size at least @variants_count to store the result - * - * This function tries to retrieve the MathGlyphConstruction for the specified - * font, glyph and direction. Note that only the value of - * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list - * of size variants as an array of hb_ot_math_glyph_variant_t structs. - * - * Return value: the total number of size variants available or 0 - * - * Since: 1.3.3 - **/ -unsigned int -hb_ot_math_get_glyph_variants (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *variants_count, /* IN/OUT */ - hb_ot_math_glyph_variant_t *variants /* OUT */) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_variants().get_glyph_variants (glyph, direction, font, - start_offset, - variants_count, - variants); -} - -/** - * hb_ot_math_get_min_connector_overlap: - * @font: #hb_font_t from which to retrieve the value - * @direction: direction of the stretching - * - * This function tries to retrieve the MathVariants table for the specified - * font and returns the minimum overlap of connecting glyphs to draw a glyph - * assembly in the specified direction. Note that only the value of - * #HB_DIRECTION_IS_HORIZONTAL is considered. - * - * Return value: requested min connector overlap or 0 - * - * Since: 1.3.3 - **/ -hb_position_t -hb_ot_math_get_min_connector_overlap (hb_font_t *font, - hb_direction_t direction) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_variants().get_min_connector_overlap (direction, font); -} - -/** - * hb_ot_math_get_glyph_assembly: - * @font: #hb_font_t from which to retrieve the values - * @glyph: index of the glyph to stretch - * @direction: direction of the stretching - * @start_offset: offset of the first glyph part to retrieve - * @parts_count: maximum number of glyph parts to retrieve after start_offset - * (IN) and actual number of parts retrieved (OUT) - * @parts: array of size at least @parts_count to store the result - * @italics_correction: italic correction of the glyph assembly - * - * This function tries to retrieve the GlyphAssembly for the specified font, - * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL - * is considered. It provides the information necessary to draw the glyph - * assembly as an array of #hb_ot_math_glyph_part_t. - * - * Return value: the total number of parts in the glyph assembly - * - * Since: 1.3.3 - **/ -unsigned int -hb_ot_math_get_glyph_assembly (hb_font_t *font, - hb_codepoint_t glyph, - hb_direction_t direction, - unsigned int start_offset, - unsigned int *parts_count, /* IN/OUT */ - hb_ot_math_glyph_part_t *parts, /* OUT */ - hb_position_t *italics_correction /* OUT */) -{ - const OT::MATH &math = _get_math (font->face); - return math.get_math_variants().get_glyph_parts (glyph, direction, font, - start_offset, - parts_count, - parts, - italics_correction); -} diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc new file mode 100644 index 000000000..9ef21d299 --- /dev/null +++ b/src/hb-ot-math.cc @@ -0,0 +1,272 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Igalia Author(s): Frédéric Wang + */ + +#include "hb-open-type-private.hh" + +#include "hb-ot-layout-math-table.hh" + +HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) + +static inline const OT::MATH& +_get_math (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); + + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + +retry: + const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); + + if (unlikely (!math)) + { + hb_blob_t *blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); + math = OT::Sanitizer::lock_instance (blob); + if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) + { + hb_blob_destroy (blob); + goto retry; + } + layout->math_blob = blob; + } + + return *math; +} + +/* + * OT::MATH + */ + +/** + * hb_ot_math_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of an OpenType MATH table on the + * face. If so, such a table will be loaded into memory and sanitized. You can + * then safely call other functions for math layout and shaping. + * + * Return value: #TRUE if face has a MATH table and #FALSE otherwise + * + * Since: 1.3.3 + **/ +hb_bool_t +hb_ot_math_has_data (hb_face_t *face) +{ + return &_get_math (face) != &OT::Null(OT::MATH); +} + +/** + * hb_ot_math_get_constant: + * @font: #hb_font_t from which to retrieve the value + * @constant: #hb_ot_math_constant_t the constant to retrieve + * + * This function returns the requested math constants as a #hb_position_t. + * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, + * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or + * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is + * actually an integer between 0 and 100 representing that percentage. + * + * Return value: the requested constant or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_constant (hb_font_t *font, + hb_ot_math_constant_t constant) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_constant(constant, font); +} + +/** + * hb_ot_math_get_glyph_italics_correction: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the italics correction of the glyph or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_italics_correction (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_italics_correction (glyph, font); +} + +/** + * hb_ot_math_get_glyph_top_accent_attachment: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * + * Return value: the top accent attachment of the glyph or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_top_accent_attachment (glyph, font); +} + +/** + * hb_ot_math_is_glyph_extended_shape: + * @font: a #hb_font_t to test + * @glyph: a glyph index to test + * + * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise + * + * Since: 1.3.3 + **/ +hb_bool_t +hb_ot_math_is_glyph_extended_shape (hb_face_t *face, + hb_codepoint_t glyph) +{ + const OT::MATH &math = _get_math (face); + return math.get_math_glyph_info().is_extended_shape (glyph); +} + +/** + * hb_ot_math_get_glyph_kerning: + * @font: #hb_font_t from which to retrieve the value + * @glyph: glyph index from which to retrieve the value + * @kern: the #hb_ot_math_kern_t from which to retrieve the value + * @correction_height: the correction height to use to determine the kerning. + * + * This function tries to retrieve the MathKern table for the specified font, + * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the + * MathKern table to find one value that is greater or equal to specified + * correction_height. If one is found the corresponding value from the list of + * kerns is returned and otherwise the last kern value is returned. + * + * Return value: requested kerning or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_glyph_kerning (hb_font_t *font, + hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_glyph_info().get_kerning (glyph, kern, correction_height, font); +} + +/** + * hb_ot_math_get_glyph_variants: + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first variant to retrieve + * @variants_count: maximum number of variants to retrieve after start_offset + * (IN) and actual number of variants retrieved (OUT) + * @variants: array of size at least @variants_count to store the result + * + * This function tries to retrieve the MathGlyphConstruction for the specified + * font, glyph and direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list + * of size variants as an array of hb_ot_math_glyph_variant_t structs. + * + * Return value: the total number of size variants available or 0 + * + * Since: 1.3.3 + **/ +unsigned int +hb_ot_math_get_glyph_variants (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_glyph_variants (glyph, direction, font, + start_offset, + variants_count, + variants); +} + +/** + * hb_ot_math_get_min_connector_overlap: + * @font: #hb_font_t from which to retrieve the value + * @direction: direction of the stretching + * + * This function tries to retrieve the MathVariants table for the specified + * font and returns the minimum overlap of connecting glyphs to draw a glyph + * assembly in the specified direction. Note that only the value of + * #HB_DIRECTION_IS_HORIZONTAL is considered. + * + * Return value: requested min connector overlap or 0 + * + * Since: 1.3.3 + **/ +hb_position_t +hb_ot_math_get_min_connector_overlap (hb_font_t *font, + hb_direction_t direction) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_min_connector_overlap (direction, font); +} + +/** + * hb_ot_math_get_glyph_assembly: + * @font: #hb_font_t from which to retrieve the values + * @glyph: index of the glyph to stretch + * @direction: direction of the stretching + * @start_offset: offset of the first glyph part to retrieve + * @parts_count: maximum number of glyph parts to retrieve after start_offset + * (IN) and actual number of parts retrieved (OUT) + * @parts: array of size at least @parts_count to store the result + * @italics_correction: italic correction of the glyph assembly + * + * This function tries to retrieve the GlyphAssembly for the specified font, + * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL + * is considered. It provides the information necessary to draw the glyph + * assembly as an array of #hb_ot_math_glyph_part_t. + * + * Return value: the total number of parts in the glyph assembly + * + * Since: 1.3.3 + **/ +unsigned int +hb_ot_math_get_glyph_assembly (hb_font_t *font, + hb_codepoint_t glyph, + hb_direction_t direction, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts, /* OUT */ + hb_position_t *italics_correction /* OUT */) +{ + const OT::MATH &math = _get_math (font->face); + return math.get_math_variants().get_glyph_parts (glyph, direction, font, + start_offset, + parts_count, + parts, + italics_correction); +} From f3397069479cae34e6bdc658e2875fb178b03e43 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 5 Jan 2017 01:27:49 -0800 Subject: [PATCH 0175/1326] 1.4.0 --- NEWS | 34 ++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index fb84c888a..6f733af25 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,37 @@ +Overview of changes leading to 1.4.0 +Thursday, January 5, 2017 +==================================== + +- Merged "OpenType GX" branch which adds core of support for + OpenType 1.8 Font Variations. To that extent, the relevant + new API is: + +New API: +hb_font_set_var_coords_normalized() + + with supporting API: + +New API: +HB_OT_LAYOUT_NO_VARIATIONS_INDEX +hb_ot_layout_table_find_feature_variations() +hb_ot_layout_feature_with_variations_get_lookups() +hb_shape_plan_create2() +hb_shape_plan_create_cached2() + + Currently variations in GSUB/GPOS/GDEF are fully supported, + and no other tables are supported. In particular, fvar/avar + are NOT supported, hence the hb_font_set_var_coords_normalized() + taking normalized coordinates. API to take design coordinates + will be added in the future. + + HVAR/VVAR/MVAR support will also be added to hb-ot-font in the + future. + +- Fix regression in GDEF glyph class processing. +- Add decompositions for Chakma, Limbu, and Balinese in USE shaper. +- Misc fixes. + + Overview of changes leading to 1.3.4 Monday, December 5, 2016 ==================================== diff --git a/configure.ac b/configure.ac index f985e1047..78869a99e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.3.4], + [1.4.0], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 53543f8b3e19456279c86f711feba42ce976668c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 5 Jan 2017 20:12:32 -0800 Subject: [PATCH 0176/1326] Ship UCDN and use it by default So we are not relying on version of Unicode data in glib... Fixes https://github.com/behdad/harfbuzz/issues/386 Fixes https://github.com/behdad/harfbuzz/issues/388 --- configure.ac | 12 ++++++++---- src/hb-unicode.cc | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 78869a99e..5d18f8610 100644 --- a/configure.ac +++ b/configure.ac @@ -289,9 +289,13 @@ AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin") dnl =========================================================================== -have_ucdn=true -if $have_glib || test \( $have_icu -a "x$with_icu" = "xbuiltin" \); then - have_ucdn=false +AC_ARG_WITH(ucdn, + [AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@], + [Use builtin UCDN library @<:@default=yes@:>@])],, + [with_ucdn=yes]) +have_ucdn=false +if test "x$with_ucdn" = "xyes"; then + have_ucdn=true fi if $have_ucdn; then AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions]) @@ -501,9 +505,9 @@ AC_MSG_NOTICE([ Build configuration: Unicode callbacks (you want at least one): + Builtin (UCDN): ${have_ucdn} Glib: ${have_glib} ICU: ${have_icu} - UCDN: ${have_ucdn} Font callbacks (the more the better): FreeType: ${have_freetype} diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 487d10b93..d553a7172 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -131,12 +131,12 @@ hb_unicode_funcs_get_default (void) #define HB_UNICODE_FUNCS_IMPLEMENT(set) \ return hb_##set##_get_unicode_funcs (); -#ifdef HAVE_GLIB +#if defined(HAVE_UCDN) + HB_UNICODE_FUNCS_IMPLEMENT(ucdn) +#elif defined(HAVE_GLIB) HB_UNICODE_FUNCS_IMPLEMENT(glib) #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) HB_UNICODE_FUNCS_IMPLEMENT(icu) -#elif defined(HAVE_UCDN) - HB_UNICODE_FUNCS_IMPLEMENT(ucdn) #else #define HB_UNICODE_FUNCS_NIL 1 HB_UNICODE_FUNCS_IMPLEMENT(nil) From 31f7b1bb94c2cef7ce58df52ddd1b09b42e8f596 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 5 Jan 2017 20:20:06 -0800 Subject: [PATCH 0177/1326] Add tests for USE using Marchen font and text From http://www.babelstone.co.uk/Fonts/Marchen.html --- test/shaping/Makefile.am | 1 + ...414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf | Bin 0 -> 66936 bytes test/shaping/tests/use-marchen.tests | 35 ++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf create mode 100644 test/shaping/tests/use-marchen.tests diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index 57369fd5b..f2bb95bdd 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -62,6 +62,7 @@ TESTS = \ tests/spaces.tests \ tests/simple.tests \ tests/use.tests \ + tests/use-marchen.tests \ tests/vertical.tests \ tests/zero-width-marks.tests \ $(NULL) diff --git a/test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf b/test/shaping/fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf new file mode 100644 index 0000000000000000000000000000000000000000..18881fe498e82cee67dc6d95fc6dc972052567bb GIT binary patch literal 66936 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 OK}i-2(;=7Xo literal 0 HcmV?d00001 diff --git a/test/shaping/tests/use-marchen.tests b/test/shaping/tests/use-marchen.tests new file mode 100644 index 000000000..6497178ab --- /dev/null +++ b/test/shaping/tests/use-marchen.tests @@ -0,0 +1,35 @@ +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8F:[u11C8F=0+3000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C71:[u11C71=0+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11CB5:[u11C8A=0+2000|u11CB5=0@-2000,0+0] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C84,U+11C71:[u11C84=0+2200|u11C71=1+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7E,U+11C8A:[u11C7E=0+2600|u11C8A=1+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11C92,U+11CA9:[u11C8A.11C92.11CA9=0+2600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11C94,U+11CA9:[u11C8A.11C94.11CA9=0+2600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C92,U+11CA9:[u11C8D.11C92.11CA9=0+2600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C94,U+11CA9:[u11C8D.11C94.11CA9=0+2600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9E,U+11CA9:[u11C8D.11C9E.11CA9=0+3200] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA0,U+11CA9:[u11C8D.11CA0.11CA9=0+3000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C92,U+11CAA:[u11C8D.11C92.11CAA=0+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C94,U+11CAA:[u11C8D.11C94.11CAA=0+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9D,U+11CAA:[u11C8D.11C9D.11CAA=0+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11C9E,U+11CAA:[u11C8D.11C9E.11CAA=0+2600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA0,U+11CAA:[u11C8D.11CA0.11CAA=0+2400] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C72,U+11CAA:[u11C80=0+2400|u11C72.11CAA=1+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8C,U+11CB1,U+11C8D:[u11C8C.11CB1=0+2793|u11C8D=2+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C7C,U+11CB3:[u11C80=0+2400|u11C7C.11CB3=1+2200] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7F,U+11CB2,U+11C7D:[u11C7F.11CB2=0+2400|u11C7D=2+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CB2,U+11C81:[u11C8D.11CB2=0+2000|u11C81=2+2400] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8C,U+11CB4,U+11C74:[u11C8C.11CB4=0+2800|u11C74=2+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8A,U+11CA1,U+11CA9,U+11C71:[u11C8A.11CA1.11CA9=0+3000|u11C71=3+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA1,U+11CA9,U+11C71:[u11C8D.11CA1.11CA9=0+3000|u11C71=3+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8D,U+11CA1,U+11CAA,U+11C71:[u11C8D.11CA1.11CAA=0+2400|u11C71=3+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8F,U+11CB0,U+11CB4,U+11CB6:[u11C8F.11CB0.11CB4=0+3600|u11CB6=0@-3200,0+0] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8E,U+11CB0,U+11CB2,U+11CB5:[u11C8E.11CB0.11CB2=0+2000|u11CB5=0@-2000,0+0] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C74,U+11C89,U+11CB2,U+11C75:[u11C74=0+2000|u11C89.11CB2=1+2000|u11C75=3+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C7C,U+11CAA,U+11CB2,U+11C75:[u11C7C.11CAA.11CB2=0+2200|u11C75=3+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C81,U+11C74,U+11CB2,U+11C8B:[u11C81=0+2400|u11C74.11CB2=1+2000|u11C8B=3+2400] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8B,U+11CB3,U+11C74,U+11C8D:[u11C8B.11CB3=0+2400|u11C74=2+2000|u11C8D=3+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C83,U+11CB4,U+11C74,U+11C8D:[u11C83.11CB4=0+2800|u11C74=2+2000|u11C8D=3+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C8B,U+11CB3,U+11C74,U+11C8D,U+11C71:[u11C8B.11CB3=0+2400|u11C74=2+2000|u11C8D=3+2000|u11C71=4+1600] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C76,U+11CB1,U+11C75,U+11C8D:[u11C80=0+2400|u11C76.11CB1=1+3200|u11C75=3+2000|u11C8D=4+2000] +fonts/sha1sum/85414f2552b654585b7a8d13dcc3e8fd9f7970a3.ttf::U+11C80,U+11C8D,U+11C94,U+11CAA,U+11CB1,U+11C74,U+11C8D:[u11C80=0+2400|u11C8D.11C94.11CAA.11CB1.shorti=1+2600|u11C74=5+2000|u11C8D=6+2000] From af596a5655ee2ed09da17a7de79f619e1547dcd9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 5 Jan 2017 20:24:41 -0800 Subject: [PATCH 0178/1326] 1.4.1 --- NEWS | 10 ++++++++++ configure.ac | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 6f733af25..8c3ef117d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,13 @@ +Overview of changes leading to 1.4.1 +Thursday, January 5, 2017 +==================================== + +- Always build and use UCDN for Unicode data by default. + Reduces dependence on version of Unicode data in glib, + specially in the Windows bundles we are shipping, which + have very old glib. + + Overview of changes leading to 1.4.0 Thursday, January 5, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 5d18f8610..32dcf18ed 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.0], + [1.4.1], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 1b00a3b0488a5d1c6ede141ae0545e2eb9af0ed8 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sun, 30 Oct 2016 20:16:41 +0200 Subject: [PATCH 0179/1326] [graphite] Fix shaping with varying font sizes Shape using design units and scale the output. See https://bugs.documentfoundation.org/show_bug.cgi?id=103403#c7 --- src/hb-graphite2.cc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index a2d90db87..dc87795c0 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -164,9 +164,10 @@ _hb_graphite2_shaper_font_data_create (hb_font_t *font) if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL; hb_face_t *face = font->face; + unsigned int upem = hb_face_get_upem (face); hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface); + return gr_make_font_with_advance_fn (upem, font, &hb_graphite2_get_advance, face_data->grface); } void @@ -230,7 +231,6 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, { hb_face_t *face = font->face; gr_face *grface = HB_SHAPER_DATA_GET (face)->grface; - gr_font *grfont = HB_SHAPER_DATA_GET (font); const char *lang = hb_language_to_string (hb_buffer_get_language (buffer)); const char *lang_end = lang ? strchr (lang, '-') : NULL; @@ -262,7 +262,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, hb_tag_t script_tag[2]; hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]); - seg = gr_make_seg (grfont, grface, + seg = gr_make_seg (NULL, grface, script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1], feats, gr_utf32, chars, buffer->len, @@ -373,7 +373,10 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, } buffer->len = glyph_count; - float yscale = font->y_scale / font->x_scale; + unsigned int upem = hb_face_get_upem (face); + float xscale = (float) font->x_scale / upem; + float yscale = (float) font->y_scale / upem; + yscale *= yscale / xscale; /* Positioning. */ if (!HB_DIRECTION_IS_BACKWARD(buffer->props.direction)) { @@ -383,16 +386,16 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, curradvx = 0; for (is = gr_seg_first_slot (seg); is; pPos++, ++info, is = gr_slot_next_in_segment (is)) { - pPos->x_offset = gr_slot_origin_X (is) - curradvx; + pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx; pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; if (info->cluster != currclus) { - pPos->x_advance = info->var1.i32; + pPos->x_advance = info->var1.i32 * xscale; curradvx += pPos->x_advance; currclus = info->cluster; } else pPos->x_advance = 0.; - pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale; curradvy += pPos->y_advance; } } @@ -401,20 +404,20 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, int currclus = -1; const hb_glyph_info_t *info = buffer->info; hb_glyph_position_t *pPos = hb_buffer_get_glyph_positions (buffer, NULL); - curradvx = gr_seg_advance_X(seg); + curradvx = gr_seg_advance_X(seg) * xscale; for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is)) { if (info->cluster != currclus) { - pPos->x_advance = info->var1.i32; - if (currclus != -1) curradvx -= info[-1].var1.i32; + pPos->x_advance = info->var1.i32 * xscale; + if (currclus != -1) curradvx -= info[-1].var1.i32 * xscale; currclus = info->cluster; } else pPos->x_advance = 0.; - pPos->y_advance = gr_slot_advance_Y (is, grface, grfont) * yscale; + pPos->y_advance = gr_slot_advance_Y (is, grface, NULL) * yscale; curradvy -= pPos->y_advance; - pPos->x_offset = gr_slot_origin_X (is) - curradvx + pPos->x_advance; + pPos->x_offset = gr_slot_origin_X (is) * xscale - curradvx + pPos->x_advance; pPos->y_offset = gr_slot_origin_Y (is) * yscale - curradvy; } hb_buffer_reverse_clusters (buffer); From b435c7c46a46350771e837e87fee448fd9dc06d3 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Fri, 11 Nov 2016 02:16:39 +0200 Subject: [PATCH 0180/1326] [graphite] Stop creating unused gr_face It is unused after previous commit, hb_graphite2_font_get_gr_font() makes no sense now so deprecating it. --- src/hb-graphite2.cc | 22 +++++----------------- src/hb-graphite2.h | 4 ++++ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index dc87795c0..f253a5f72 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -27,7 +27,6 @@ */ #define HB_SHAPER graphite2 -#define hb_graphite2_shaper_font_data_t gr_font #include "hb-shaper-impl-private.hh" #include "hb-graphite2.h" @@ -153,27 +152,17 @@ hb_graphite2_face_get_gr_face (hb_face_t *face) * shaper font data */ -static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid) -{ - return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid); -} +struct hb_graphite2_shaper_font_data_t {}; hb_graphite2_shaper_font_data_t * -_hb_graphite2_shaper_font_data_create (hb_font_t *font) +_hb_graphite2_shaper_font_data_create (hb_font_t *font HB_UNUSED) { - if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL; - - hb_face_t *face = font->face; - unsigned int upem = hb_face_get_upem (face); - hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - - return gr_make_font_with_advance_fn (upem, font, &hb_graphite2_get_advance, face_data->grface); + return (hb_graphite2_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void -_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data) +_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data HB_UNUSED) { - gr_font_destroy (data); } /* @@ -182,8 +171,7 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data) gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font) { - if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL; - return HB_SHAPER_DATA_GET (font); + return NULL; } diff --git a/src/hb-graphite2.h b/src/hb-graphite2.h index 122c3e476..82b1e64cd 100644 --- a/src/hb-graphite2.h +++ b/src/hb-graphite2.h @@ -39,9 +39,13 @@ HB_BEGIN_DECLS HB_EXTERN gr_face * hb_graphite2_face_get_gr_face (hb_face_t *face); +#ifndef HB_DISABLE_DEPRECATED + HB_EXTERN gr_font * hb_graphite2_font_get_gr_font (hb_font_t *font); +#endif + HB_END_DECLS From 7cf9952e7fc015d0b08d3de6c95357662d57ad8d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 8 Jan 2017 23:55:54 -0800 Subject: [PATCH 0181/1326] [USE] Remove non-canonical decompositions We have had added this in Indic shaper to assist shaping these scripts. In Universal Shaping Engine however, it is up to font designer to decompose them. Hence moving them from Indic shaper to USE was wrong. Fixup for f6ba63b2e8eb577385f70758efdd3b8408c8a9cb Part of fixing https://github.com/behdad/harfbuzz/issues/387 --- src/hb-ot-shape-complex-use.cc | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 5b19d5d74..af6870686 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -572,28 +572,6 @@ decompose_use (const hb_ot_shape_normalize_context_t *c, */ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; - - /* - * Decompose split matras that don't have Unicode decompositions. - */ - - /* Limbu */ - case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; - case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; - - /* Balinese */ - case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - -#if 0 - /* Lepcha */ - case 0x1C29u : *a = no decomp, -> LEFT; return true; - - /* Javanese */ - case 0xA9C0u : *a = no decomp, -> RIGHT; return true; - - /* Sharada */ - case 0x111BFu : *a = no decomp, -> ABOVE; return true; -#endif } return (bool) c->unicode->decompose (ab, a, b); From 00adf9c8a4573a2b3ef61991197821af03bca310 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 00:00:49 -0800 Subject: [PATCH 0182/1326] Minor Should be enough to get -hangul.cc out of SOURCES in Firefox build: https://dxr.mozilla.org/mozilla-central/source/gfx/harfbuzz/src/moz.build No one else should care! --- src/hb-ot-shape-complex-hangul.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc index eb95a28c0..af5056522 100644 --- a/src/hb-ot-shape-complex-hangul.cc +++ b/src/hb-ot-shape-complex-hangul.cc @@ -32,7 +32,7 @@ /* Same order as the feature array below */ enum { - NONE, + _JMO, LJMO, VJMO, From ebf927d3d4394159e480fec2042a0456df8dd0f4 Mon Sep 17 00:00:00 2001 From: ebraminio Date: Mon, 9 Jan 2017 13:12:09 +0330 Subject: [PATCH 0183/1326] Make UCDN default enabled (fixes #389) (#391) --- win32/config-msvc.mak | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak index ecbbe92fd..4cffaeacc 100644 --- a/win32/config-msvc.mak +++ b/win32/config-msvc.mak @@ -184,9 +184,10 @@ HB_CFLAGS = $(HB_CFLAGS) /DU_HAVE_INT8_T HB_SOURCES = $(HB_SOURCES) $(HB_ICU_sources) HB_HEADERS = $(HB_HEADERS) $(HB_ICU_headers) HB_DEP_LIBS = $(HB_DEP_LIBS) $(HB_ICU_DEP_LIBS) -!else -# If there is no GLib support, use the built-in UCDN -# and define some of the macros in GLib's msvc_recommended_pragmas.h +!endif + +!if "$(UCDN)" != "0" +# Define some of the macros in GLib's msvc_recommended_pragmas.h # to reduce some unneeded build-time warnings HB_DEFINES = $(HB_DEFINES) /DHAVE_UCDN=1 HB_CFLAGS = \ From 3b5263b0e9e23e56e14ce6a8498c21c5ce95cc35 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 15:49:08 -0800 Subject: [PATCH 0184/1326] Typo --- src/hb-ot-layout-math-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-layout-math-table.hh index b52b1215d..7d1adf337 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-layout-math-table.hh @@ -716,7 +716,7 @@ struct MATH DEFINE_SIZE_STATIC (10); }; -} /* mathspace OT */ +} /* namespace OT */ #endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ From 93ef684b9bc411b7642df3adeb2248ad6010ee66 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 21:11:00 -0800 Subject: [PATCH 0185/1326] Rename hb-ot-layout-math-table.hh to hb-ot-math-table.hh --- src/Makefile.sources | 2 +- src/{hb-ot-layout-math-table.hh => hb-ot-math-table.hh} | 6 +++--- src/hb-ot-math.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/{hb-ot-layout-math-table.hh => hb-ot-math-table.hh} (99%) diff --git a/src/Makefile.sources b/src/Makefile.sources index e72759842..b75ec0cbd 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -76,11 +76,11 @@ HB_OT_sources = \ hb-ot-layout-gsubgpos-private.hh \ hb-ot-layout-gsub-table.hh \ hb-ot-layout-jstf-table.hh \ - hb-ot-layout-math-table.hh \ hb-ot-layout-private.hh \ hb-ot-map.cc \ hb-ot-map-private.hh \ hb-ot-math.cc \ + hb-ot-math-table.hh \ hb-ot-shape.cc \ hb-ot-shape-complex-arabic.cc \ hb-ot-shape-complex-arabic-fallback.hh \ diff --git a/src/hb-ot-layout-math-table.hh b/src/hb-ot-math-table.hh similarity index 99% rename from src/hb-ot-layout-math-table.hh rename to src/hb-ot-math-table.hh index 7d1adf337..191d79e98 100644 --- a/src/hb-ot-layout-math-table.hh +++ b/src/hb-ot-math-table.hh @@ -24,8 +24,8 @@ * Igalia Author(s): Frédéric Wang */ -#ifndef HB_OT_LAYOUT_MATH_TABLE_HH -#define HB_OT_LAYOUT_MATH_TABLE_HH +#ifndef HB_OT_MATH_TABLE_HH +#define HB_OT_MATH_TABLE_HH #include "hb-open-type-private.hh" #include "hb-ot-layout-common-private.hh" @@ -719,4 +719,4 @@ struct MATH } /* namespace OT */ -#endif /* HB_OT_LAYOUT_MATH_TABLE_HH */ +#endif /* HB_OT_MATH_TABLE_HH */ diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 9ef21d299..3028cc494 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -26,7 +26,7 @@ #include "hb-open-type-private.hh" -#include "hb-ot-layout-math-table.hh" +#include "hb-ot-math-table.hh" HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) From 29fb0cb727555ea60460d794a3c6f30179546af9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 21:18:55 -0800 Subject: [PATCH 0186/1326] Minor --- src/hb-face-private.hh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh index c4266fff4..43e7b1cb3 100644 --- a/src/hb-face-private.hh +++ b/src/hb-face-private.hh @@ -50,12 +50,16 @@ struct hb_face_t { void *user_data; hb_destroy_func_t destroy; - unsigned int index; - mutable unsigned int upem; - mutable unsigned int num_glyphs; + unsigned int index; /* Face index in a collection, zero-based. */ + mutable unsigned int upem; /* Units-per-EM. */ + mutable unsigned int num_glyphs; /* Number of glyphs. */ - struct hb_shaper_data_t shaper_data; + struct hb_shaper_data_t shaper_data; /* Various shaper data. */ + /* Various non-shaping data. */ + /* ... */ + + /* Cache */ struct plan_node_t { hb_shape_plan_t *shape_plan; plan_node_t *next; From ac274331c285e1b42632870e150e1d66a9e21933 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 22:20:38 -0800 Subject: [PATCH 0187/1326] In lazy-loading, remember allocation failure --- src/hb-ot-font.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 5be055d34..c2431364d 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -447,11 +447,13 @@ struct hb_lazy_loader_t { p = (T *) calloc (1, sizeof (T)); if (unlikely (!p)) - return &OT::Null(T); - p->init (face); + p = const_cast (&OT::Null(T)); + else + p->init (face); if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p))) { - p->fini (); + if (p != &OT::Null(T)) + p->fini (); goto retry; } } From 1af9d924a474f210fda10b5e8ab6b388241aa0b5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 22:22:37 -0800 Subject: [PATCH 0188/1326] Move lazy-loader to more generic place --- src/hb-open-type-private.hh | 47 ++++++++++++++++++++++++++++++++++++ src/hb-ot-font.cc | 48 ++----------------------------------- 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 2cc1fb20d..a8756d466 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -1061,6 +1061,53 @@ struct SortedArrayOf : ArrayOf }; +/* Lazy struct and blob loaders. */ + +template +struct hb_lazy_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = NULL; + } + + inline void fini (void) + { + if (instance && instance != &OT::Null(T)) + { + instance->fini(); + free (instance); + } + } + + inline const T* operator-> (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + p = (T *) calloc (1, sizeof (T)); + if (unlikely (!p)) + p = const_cast (&OT::Null(T)); + else + p->init (face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p))) + { + if (p != &OT::Null(T)) + p->fini (); + goto retry; + } + } + return p; + } + + private: + hb_face_t *face; + T *instance; +}; + + } /* namespace OT */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index c2431364d..c4ec612c8 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -421,57 +421,13 @@ struct hb_ot_face_cmap_accelerator_t } }; -template -struct hb_lazy_loader_t -{ - inline void init (hb_face_t *face_) - { - face = face_; - instance = NULL; - } - - inline void fini (void) - { - if (instance && instance != &OT::Null(T)) - { - instance->fini(); - free (instance); - } - } - - inline const T* operator-> (void) const - { - retry: - T *p = (T *) hb_atomic_ptr_get (&instance); - if (unlikely (!p)) - { - p = (T *) calloc (1, sizeof (T)); - if (unlikely (!p)) - p = const_cast (&OT::Null(T)); - else - p->init (face); - if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p))) - { - if (p != &OT::Null(T)) - p->fini (); - goto retry; - } - } - return p; - } - - private: - hb_face_t *face; - T *instance; -}; - struct hb_ot_font_t { hb_ot_face_cmap_accelerator_t cmap; hb_ot_face_metrics_accelerator_t h_metrics; hb_ot_face_metrics_accelerator_t v_metrics; - hb_lazy_loader_t glyf; - hb_lazy_loader_t cbdt; + OT::hb_lazy_loader_t glyf; + OT::hb_lazy_loader_t cbdt; }; From ebbcc1112229cde9ed469efdfeac7ef79dfcd834 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 22:45:25 -0800 Subject: [PATCH 0189/1326] Add hb_lazy_table_loader_t --- src/hb-open-type-private.hh | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index a8756d466..6ee4fae9e 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -30,6 +30,7 @@ #define HB_OPEN_TYPE_PRIVATE_HH #include "hb-private.hh" +#include "hb-face-private.hh" namespace OT { @@ -1107,6 +1108,45 @@ struct hb_lazy_loader_t T *instance; }; +template +struct hb_lazy_table_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = NULL; + blob = NULL; + } + + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline const T* operator-> (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); + p = OT::Sanitizer::lock_instance (blob); + if (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p)) + { + hb_blob_destroy (blob_); + goto retry; + } + blob = blob_; + } + return p; + } + + private: + hb_face_t *face; + T *instance; + hb_blob_t *blob; +}; + } /* namespace OT */ From 1f810daf1640f279c2f7aad8c312664cf2293987 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 9 Jan 2017 23:50:56 -0800 Subject: [PATCH 0190/1326] Port math table to hb_lazy_table_loader_t --- src/hb-open-type-private.hh | 22 +++++++++++++++++----- src/hb-ot-layout-private.hh | 4 ++-- src/hb-ot-layout.cc | 7 +++---- src/hb-ot-math.cc | 17 +---------------- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 6ee4fae9e..e0d5fae6f 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -1064,6 +1064,7 @@ struct SortedArrayOf : ArrayOf /* Lazy struct and blob loaders. */ +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ template struct hb_lazy_loader_t { @@ -1082,7 +1083,7 @@ struct hb_lazy_loader_t } } - inline const T* operator-> (void) const + inline const T* get (void) const { retry: T *p = (T *) hb_atomic_ptr_get (&instance); @@ -1103,11 +1104,17 @@ struct hb_lazy_loader_t return p; } + inline const T* operator-> (void) const + { + return get (); + } + private: hb_face_t *face; T *instance; }; +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ template struct hb_lazy_table_loader_t { @@ -1123,14 +1130,14 @@ struct hb_lazy_table_loader_t hb_blob_destroy (blob); } - inline const T* operator-> (void) const + inline const T* get (void) const { retry: - T *p = (T *) hb_atomic_ptr_get (&instance); + const T *p = (T *) hb_atomic_ptr_get (&instance); if (unlikely (!p)) { hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); - p = OT::Sanitizer::lock_instance (blob); + p = OT::Sanitizer::lock_instance (blob_); if (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p)) { hb_blob_destroy (blob_); @@ -1141,10 +1148,15 @@ struct hb_lazy_table_loader_t return p; } + inline const T* operator-> (void) const + { + return get(); + } + private: hb_face_t *face; T *instance; - hb_blob_t *blob; + mutable hb_blob_t *blob; }; diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index a4272de63..1c398e9bd 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -34,6 +34,7 @@ #include "hb-font-private.hh" #include "hb-buffer-private.hh" #include "hb-set-private.hh" +#include "hb-open-type-private.hh" /* Private API corresponding to hb-ot-layout.h: */ @@ -153,12 +154,11 @@ struct hb_ot_layout_t hb_blob_t *gdef_blob; hb_blob_t *gsub_blob; hb_blob_t *gpos_blob; - hb_blob_t *math_blob; const struct OT::GDEF *gdef; const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; - const struct OT::MATH *math; + OT::hb_lazy_table_loader_t math; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 145ec7638..d1654025e 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -60,9 +60,7 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); - /* The MATH table is rarely used, so only try and load it in _get_math. */ - layout->math_blob = NULL; - layout->math = NULL; + layout->math.init (face); { /* @@ -181,7 +179,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); - hb_blob_destroy (layout->math_blob); + + layout->math.fini (); free (layout); } diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 3028cc494..40414ebee 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -37,22 +37,7 @@ _get_math (hb_face_t *face) hb_ot_layout_t * layout = hb_ot_layout_from_face (face); -retry: - const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); - - if (unlikely (!math)) - { - hb_blob_t *blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_MATH)); - math = OT::Sanitizer::lock_instance (blob); - if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) - { - hb_blob_destroy (blob); - goto retry; - } - layout->math_blob = blob; - } - - return *math; + return *(layout->math.get ()); } /* From 784d1180de19fbf4948f08ee2124277cc06066dd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Jan 2017 11:58:13 -0800 Subject: [PATCH 0191/1326] Fix build with clang --- src/hb-open-type-private.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index e0d5fae6f..8845e3eee 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -1133,11 +1133,11 @@ struct hb_lazy_table_loader_t inline const T* get (void) const { retry: - const T *p = (T *) hb_atomic_ptr_get (&instance); + T *p = (T *) hb_atomic_ptr_get (&instance); if (unlikely (!p)) { hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); - p = OT::Sanitizer::lock_instance (blob_); + p = const_cast(OT::Sanitizer::lock_instance (blob_)); if (!hb_atomic_ptr_cmpexch (const_cast(&instance), NULL, p)) { hb_blob_destroy (blob_); From 1337428e4f8a2a4c78312c581bf4e96cd49d783f Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Wed, 18 Jan 2017 13:51:02 +0100 Subject: [PATCH 0192/1326] Update language tags to OpenType 1.8.1 (#403) Resolves https://github.com/behdad/harfbuzz/issues/324 --- src/hb-ot-tag.cc | 77 +++++++++++++++++++++++++++++++++++++----- test/api/test-ot-tag.c | 58 +++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 5f21ac096..5c348e898 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -201,6 +201,7 @@ static const LangTag ot_languages[] = { {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ + {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic */ {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ @@ -239,6 +240,7 @@ static const LangTag ot_languages[] = { {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ + {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin */ {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ @@ -270,8 +272,10 @@ static const LangTag ot_languages[] = { {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */ {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ + {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ + {"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */ {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ @@ -279,8 +283,17 @@ static const LangTag ot_languages[] = { {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */ + {"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */ + {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */ {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ + {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */ + {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */ + {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */ + {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */ + {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */ + {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ {"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ @@ -293,6 +306,9 @@ static const LangTag ot_languages[] = { {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ + {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */ + {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */ + {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */ {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ @@ -300,7 +316,9 @@ static const LangTag ot_languages[] = { {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */ + {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */ {"da", HB_TAG('D','A','N',' ')}, /* Danish */ + {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin */ {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ {"dax", HB_TAG('D','A','X',' ')}, /* Dayi */ @@ -343,7 +361,7 @@ static const LangTag ot_languages[] = { {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ - {"flm", HB_TAG('H','A','L',' ')}, /* Halam */ + {"flm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin [retired ISO639 code] */ {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ {"fr", HB_TAG('F','R','A',' ')}, /* French */ @@ -390,6 +408,7 @@ static const LangTag ot_languages[] = { {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ + {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin */ {"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */ {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ @@ -553,6 +572,7 @@ static const LangTag ot_languages[] = { {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ + {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin */ {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ @@ -617,6 +637,7 @@ static const LangTag ot_languages[] = { {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ + {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin */ {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ @@ -674,6 +695,7 @@ static const LangTag ot_languages[] = { {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ + {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin */ {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ @@ -713,12 +735,15 @@ static const LangTag ot_languages[] = { {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ + {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac */ {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ + {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin */ {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ + {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin */ {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ @@ -786,11 +811,13 @@ static const LangTag ot_languages[] = { {"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */ {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ + {"yos", HB_TAG('Q','I','N',' ')}, /* Yos, deprecated by IANA in favor of Zou [zom] */ {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ + {"zom", HB_TAG('Q','I','N',' ')}, /* Zou */ {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */ {"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */ @@ -907,6 +934,30 @@ hb_ot_tag_from_language (hb_language_t language) return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */ } + /* + * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syre")) { + return HB_TAG('S','Y','R','E'); /* Estrangela Syriac */ + } + + /* + * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrj")) { + return HB_TAG('S','Y','R','J'); /* Western Syriac */ + } + + /* + * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrn")) { + return HB_TAG('S','Y','R','N'); /* Eastern Syriac */ + } + /* Find a language matching in the first component */ { const LangTag *lang_tag; @@ -962,6 +1013,22 @@ hb_ot_tag_to_language (hb_tag_t tag) if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) return NULL; + /* struct LangTag has only room for 3-letter language tags. */ + switch (tag) { + case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ + return hb_language_from_string ("und-fonnapa", -1); + case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ + return hb_language_from_string ("und-fonipa", -1); + case HB_TAG('S','Y','R',' '): /* Syriac [macrolanguage] */ + return hb_language_from_string ("syr", -1); + case HB_TAG('S','Y','R','E'): /* Estrangela Syriac */ + return hb_language_from_string ("und-Syre", -1); + case HB_TAG('S','Y','R','J'): /* Western Syriac */ + return hb_language_from_string ("und-Syrj", -1); + case HB_TAG('S','Y','R','N'): /* Eastern Syriac */ + return hb_language_from_string ("und-Syrn", -1); + } + for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) if (ot_languages[i].tag == tag) return hb_language_from_string (ot_languages[i].language, -1); @@ -976,14 +1043,6 @@ hb_ot_tag_to_language (hb_tag_t tag) } } - /* struct LangTag has only room for 3-letter language tags. */ - switch (tag) { - case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ - return hb_language_from_string ("und-fonnapa", -1); - case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ - return hb_language_from_string ("und-fonipa", -1); - } - /* Else return a custom language in the form of "x-hbotABCD" */ { unsigned char buf[11] = "x-hbot"; diff --git a/test/api/test-ot-tag.c b/test/api/test-ot-tag.c index e54e55269..f5cbd9d12 100644 --- a/test/api/test-ot-tag.c +++ b/test/api/test-ot-tag.c @@ -188,11 +188,48 @@ test_ot_tag_language (void) test_language_two_way ("ENG", "en"); test_tag_from_language ("ENG", "en_US"); + test_language_two_way ("CJA", "cja"); /* Western Cham */ + test_language_two_way ("CJM", "cjm"); /* Eastern Cham */ test_language_two_way ("EVN", "eve"); + test_language_two_way ("HAL", "cfm"); /* BCP47 and current ISO639-3 code for Halam/Falam Chin */ + test_tag_from_language ("HAL", "flm"); /* Retired ISO639-3 code for Halam/Falam Chin */ + + test_tag_from_language ("QIN", "bgr"); /* Bawm Chin */ + test_tag_from_language ("QIN", "cbl"); /* Bualkhaw Chin */ + test_tag_from_language ("QIN", "cka"); /* Khumi Awa Chin */ + test_tag_from_language ("QIN", "cmr"); /* Mro-Khimi Chin */ + test_tag_from_language ("QIN", "cnb"); /* Chinbon Chin */ + test_tag_from_language ("QIN", "cnh"); /* Hakha Chin */ + test_tag_from_language ("QIN", "cnk"); /* Khumi Chin */ + test_tag_from_language ("QIN", "cnw"); /* Ngawn Chin */ + test_tag_from_language ("QIN", "csh"); /* Asho Chin */ + test_tag_from_language ("QIN", "csy"); /* Siyin Chin */ + test_tag_from_language ("QIN", "ctd"); /* Tedim Chin */ + test_tag_from_language ("QIN", "czt"); /* Zotung Chin */ + test_tag_from_language ("QIN", "dao"); /* Daai Chin */ + test_tag_from_language ("QIN", "hlt"); /* Matu Chin */ + test_tag_from_language ("QIN", "mrh"); /* Mara Chin */ + test_tag_from_language ("QIN", "pck"); /* Paite Chin */ + test_tag_from_language ("QIN", "sez"); /* Senthang Chin */ + test_tag_from_language ("QIN", "tcp"); /* Tawr Chin */ + test_tag_from_language ("QIN", "tcz"); /* Thado Chin */ + test_tag_from_language ("QIN", "yos"); /* Yos, deprecated by IANA in favor of Zou [zom] */ + test_tag_from_language ("QIN", "zom"); /* Zou */ + test_tag_to_language ("QIN", "bgr"); /* no single BCP47 tag for Chin; picking Bawm Chin */ + test_language_two_way ("FAR", "fa"); test_tag_from_language ("FAR", "fa_IR"); + test_language_two_way ("SWA", "aii"); /* Swadaya Aramaic */ + + test_language_two_way ("SYR", "syr"); /* Syriac [macrolanguage] */ + test_tag_from_language ("SYR", "amw"); /* Western Neo-Aramaic */ + test_tag_from_language ("SYR", "cld"); /* Chaldean Neo-Aramaic */ + test_tag_from_language ("SYR", "syc"); /* Classical Syriac */ + + test_language_two_way ("TUA", "tru"); /* Turoyo Aramaic */ + test_language_two_way ("ZHH", "zh-hk"); /* Chinese (Hong Kong) */ test_tag_from_language ("ZHS", "zh"); /* Chinese */ @@ -238,6 +275,27 @@ test_ot_tag_language (void) test_tag_from_language ("APPH", "und-fonnapa"); test_tag_to_language ("APPH", "und-fonnapa"); + /* Estrangela Syriac */ + test_tag_from_language ("SYRE", "aii-Syre"); + test_tag_from_language ("SYRE", "de-Syre"); + test_tag_from_language ("SYRE", "syr-Syre"); + test_tag_from_language ("SYRE", "und-Syre"); + test_tag_to_language ("SYRE", "und-Syre"); + + /* Western Syriac */ + test_tag_from_language ("SYRJ", "aii-Syrj"); + test_tag_from_language ("SYRJ", "de-Syrj"); + test_tag_from_language ("SYRJ", "syr-Syrj"); + test_tag_from_language ("SYRJ", "und-Syrj"); + test_tag_to_language ("SYRJ", "und-Syrj"); + + /* Eastern Syriac */ + test_tag_from_language ("SYRN", "aii-Syrn"); + test_tag_from_language ("SYRN", "de-Syrn"); + test_tag_from_language ("SYRN", "syr-Syrn"); + test_tag_from_language ("SYRN", "und-Syrn"); + test_tag_to_language ("SYRN", "und-Syrn"); + /* Test that x-hbot overrides the base language */ test_tag_from_language ("ABC", "fa-x-hbotabc-zxc"); test_tag_from_language ("ABC", "fa-ir-x-hbotabc-zxc"); From 2452543fdd383e62b8c4bc44b11bfd6796fc9963 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Wed, 18 Jan 2017 22:48:13 +0200 Subject: [PATCH 0193/1326] [ot] Fix automatic fraction for RTL scripts (#405) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The numbers for right-to-left scripts are processed also from right to left, so the order of applying “numr” and “dnom” features should be reversed in such case. Fixes https://github.com/behdad/harfbuzz/issues/395 --- src/hb-ot-shape.cc | 16 ++++++++++++++-- test/shaping/Makefile.am | 1 + ...15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf | Bin 0 -> 4936 bytes test/shaping/tests/automatic-fractions.tests | 3 +++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf create mode 100644 test/shaping/tests/automatic-fractions.tests diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index ddd6662e8..6b38739c9 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -362,6 +362,18 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) hb_buffer_t *buffer = c->buffer; + hb_mask_t pre_mask, post_mask; + if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) + { + pre_mask = c->plan->numr_mask | c->plan->frac_mask; + post_mask = c->plan->frac_mask | c->plan->dnom_mask; + } + else + { + pre_mask = c->plan->frac_mask | c->plan->dnom_mask; + post_mask = c->plan->numr_mask | c->plan->frac_mask; + } + /* TODO look in pre/post context text also. */ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; @@ -380,10 +392,10 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) end++; for (unsigned int j = start; j < i; j++) - info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; + info[j].mask |= pre_mask; info[i].mask |= c->plan->frac_mask; for (unsigned int j = i + 1; j < end; j++) - info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; + info[j].mask |= post_mask; i = end - 1; } diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index f2bb95bdd..ea0b28a7e 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -43,6 +43,7 @@ CLEANFILES += \ TESTS = \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ + tests/automatic-fractions.tests \ tests/cluster.tests \ tests/color-fonts.tests \ tests/context-matching.tests \ diff --git a/test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf b/test/shaping/fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4b80f80443b099f82927f924a4434818d76394ad GIT binary patch literal 4936 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 literal 0 HcmV?d00001 diff --git a/test/shaping/tests/automatic-fractions.tests b/test/shaping/tests/automatic-fractions.tests new file mode 100644 index 000000000..f9510e26c --- /dev/null +++ b/test/shaping/tests/automatic-fractions.tests @@ -0,0 +1,3 @@ +fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf::U+0031,U+0032,U+0033,U+2044,U+0034,U+0035,U+0036:[one.numr=0+600|two.numr=1+600|three.numr=2+600|fraction=3+252|four.small=4+600|five.small=5+600|six.small=6+600] +fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf:--direction=l --script=arab:U+0031,U+0032,U+0033,U+2044,U+0034,U+0035,U+0036:[one.numr=0+600|two.numr=1+600|three.numr=2+600|fraction=3+252|four.small=4+600|five.small=5+600|six.small=6+600] +fonts/sha1sum/15dfc433a135a658b9f4b1a861b5cdd9658ccbb9.ttf:--direction=l:U+0661,U+0662,U+0663,U+2044,U+0664,U+0665,U+0666:[uni0661.numr=0+600|uni0662.numr=1+600|uni0663.numr=2+600|fraction=3+252|uni0664.small=4+600|uni0665.small=5+600|uni0666.small=6+600] From 2f2ceee1853649d1b2ad4315a38cd9c07659932a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 16:48:01 -0800 Subject: [PATCH 0194/1326] Minor --- test/api/test-ot-math.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index 049656a03..cfac10900 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -70,12 +70,13 @@ openFont(const char* fontFile) if ((ft_error = FT_Set_Char_Size (ft_face, 2000, 1000, 0, 0))) abort(); hb_font = hb_ft_font_create (ft_face, NULL); - hb_face = hb_ft_face_create_cached(ft_face); + hb_face = hb_face_reference (hb_font_get_face (hb_font)); } static inline void closeFont (void) { + hb_face_destroy (hb_face); hb_font_destroy (hb_font); FT_Done_Face (ft_face); } From b5ecf1bfa459a755e36bc4c7f545c7f803b7d016 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 16:50:29 -0800 Subject: [PATCH 0195/1326] Fix warnings --- test/api/test-ot-math.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index cfac10900..e7a6fc899 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -401,6 +401,11 @@ static void test_get_glyph_variants (void) { hb_codepoint_t glyph; + hb_ot_math_glyph_variant_t variants[20]; + unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); + unsigned int count; + unsigned int offset = 0; + initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); @@ -464,10 +469,6 @@ test_get_glyph_variants (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowleft", -1, &glyph)); - hb_ot_math_glyph_variant_t variants[20]; - unsigned variantsSize = sizeof (variants) / sizeof (variants[0]); - unsigned int count; - unsigned int offset = 0; do { count = variantsSize; hb_ot_math_get_glyph_variants (hb_font, @@ -524,6 +525,11 @@ static void test_get_glyph_assembly (void) { hb_codepoint_t glyph; + hb_ot_math_glyph_part_t parts[20]; + unsigned partsSize = sizeof (parts) / sizeof (parts[0]); + unsigned int count; + unsigned int offset = 0; + initFreeType(); openFont("fonts/MathTestFontEmpty.otf"); @@ -591,10 +597,6 @@ test_get_glyph_assembly (void) NULL), ==, 0); g_assert(hb_font_get_glyph_from_name (hb_font, "arrowright", -1, &glyph)); - hb_ot_math_glyph_part_t parts[20]; - unsigned partsSize = sizeof (parts) / sizeof (parts[0]); - unsigned int count; - unsigned int offset = 0; do { count = partsSize; hb_ot_math_get_glyph_assembly (hb_font, From 331d07bd40a3d9ff30db5cdf85fdc4f10f0fcb99 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 16:51:36 -0800 Subject: [PATCH 0196/1326] Minor --- test/api/test-ot-math.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index e7a6fc899..b9fcb656d 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -79,6 +79,9 @@ closeFont (void) hb_face_destroy (hb_face); hb_font_destroy (hb_font); FT_Done_Face (ft_face); + hb_face = NULL; + hb_font = NULL; + ft_face = NULL; } static void From a8a5e81a52f56f5f8bf975dc4d9f79bede5d895b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 16:55:04 -0800 Subject: [PATCH 0197/1326] [test-ot-math] Add test with nil face/font --- test/api/test-ot-math.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/api/test-ot-math.c b/test/api/test-ot-math.c index b9fcb656d..0ca5566df 100644 --- a/test/api/test-ot-math.c +++ b/test/api/test-ot-math.c @@ -97,6 +97,14 @@ test_has_data (void) g_assert(hb_ot_math_has_data (hb_face)); // MATH table available closeFont(); + hb_face = hb_face_get_empty (); + hb_font = hb_font_create (hb_face); + g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + + hb_font = hb_font_get_empty (); + hb_face = hb_font_get_face (hb_font); + g_assert(!hb_ot_math_has_data (hb_face)); // MATH table not available + cleanupFreeType(); } From 272b5115325b785e92ff5500d4bfc3a67490b6f8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 19:33:07 -0800 Subject: [PATCH 0198/1326] Minor --- src/hb-ot-math.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 40414ebee..ec8df2c25 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -49,10 +49,9 @@ _get_math (hb_face_t *face) * @face: #hb_face_t to test * * This function allows to verify the presence of an OpenType MATH table on the - * face. If so, such a table will be loaded into memory and sanitized. You can - * then safely call other functions for math layout and shaping. + * face. * - * Return value: #TRUE if face has a MATH table and #FALSE otherwise + * Return value: true if face has a MATH table, false otherwise * * Since: 1.3.3 **/ @@ -124,7 +123,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * @font: a #hb_font_t to test * @glyph: a glyph index to test * - * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise + * Return value: true if the glyph is an extended shape, false otherwise * * Since: 1.3.3 **/ From 55d42fd667b9c34a1109bb850bf2ea7322c01040 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 19 Jan 2017 19:35:48 -0800 Subject: [PATCH 0199/1326] Start adding hb-ot-var.h and implementation Supports enumerating variation axes, normalizing values, etc. --- src/Makefile.sources | 3 + src/hb-ot-layout-private.hh | 6 ++ src/hb-ot-layout.cc | 4 ++ src/hb-ot-var-fvar-table.hh | 133 ++++++++++++++++++++++++++++++++++++ src/hb-ot-var.cc | 63 +++++++++++++++++ src/hb-ot-var.h | 81 ++++++++++++++++++++++ src/hb-ot.h | 1 + 7 files changed, 291 insertions(+) create mode 100644 src/hb-ot-var-fvar-table.hh create mode 100644 src/hb-ot-var.cc create mode 100644 src/hb-ot-var.h diff --git a/src/Makefile.sources b/src/Makefile.sources index b75ec0cbd..279bc46eb 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -108,6 +108,8 @@ HB_OT_sources = \ hb-ot-shape-fallback-private.hh \ hb-ot-shape-fallback.cc \ hb-ot-shape-private.hh \ + hb-ot-var.cc \ + hb-ot-var-fvar-table.hh \ $(NULL) HB_OT_headers = \ @@ -117,6 +119,7 @@ HB_OT_headers = \ hb-ot-math.h \ hb-ot-shape.h \ hb-ot-tag.h \ + hb-ot-var.h \ $(NULL) # Optional Sources and Headers with external deps diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 1c398e9bd..8c348beb1 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -126,6 +126,8 @@ namespace OT { struct GSUB; struct GPOS; struct MATH; + struct fvar; + struct avar; } struct hb_ot_layout_lookup_accelerator_t @@ -158,7 +160,11 @@ struct hb_ot_layout_t const struct OT::GDEF *gdef; const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; + + /* TODO Move the following out of this struct. */ OT::hb_lazy_table_loader_t math; + OT::hb_lazy_table_loader_t fvar; + OT::hb_lazy_table_loader_t avar; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index d1654025e..d8d628480 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -61,6 +61,8 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); layout->math.init (face); + layout->fvar.init (face); + layout->avar.init (face); { /* @@ -181,6 +183,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gpos_blob); layout->math.fini (); + layout->fvar.fini (); + layout->avar.fini (); free (layout); } diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh new file mode 100644 index 000000000..84617411c --- /dev/null +++ b/src/hb-ot-var-fvar-table.hh @@ -0,0 +1,133 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_FVAR_TABLE_HH +#define HB_OT_VAR_FVAR_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-var.h" + +namespace OT { + + +struct InstanceRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (coordinates, coordinates[0].static_size, axis_count)); + } + + protected: + USHORT subfamilyNameID;/* The name ID for entries in the 'name' table + * that provide subfamily names for this instance. */ + USHORT reserved; /* Reserved for future use — set to 0. */ + Fixed coordinates[VAR];/* The coordinates array for this instance. */ + //USHORT postScriptNameIDX;/*Optional. The name ID for entries in the 'name' + // * table that provide PostScript names for this + // * instance. */ + + public: + DEFINE_SIZE_ARRAY (4, coordinates); +}; + +struct AxisRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + Tag axisTag; /* Tag identifying the design variation for the axis. */ + Fixed minValue; /* The minimum coordinate value for the axis. */ + Fixed defaultValue; /* The default coordinate value for the axis. */ + Fixed maxValue; /* The maximum coordinate value for the axis. */ + USHORT reserved; /* Reserved for future use — set to 0. */ + USHORT axisNameID; /* The name ID for entries in the 'name' table that + * provide a display name for this axis. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + + +/* + * fvar — Font Variations Table + */ + +struct fvar +{ + static const hb_tag_t tableTag = HB_OT_TAG_fvar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) /*&& + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this) && + mathVariants.sanitize (c, this)*/); + } + +#if 0 + inline hb_position_t get_constant (hb_ot_math_constant_t constant, + hb_font_t *font) const + { return (this+mathConstants).get_value (constant, font); } + + inline const MathGlyphInfo &get_math_glyph_info (void) const + { return this+mathGlyphInfo; } + + inline const MathVariants &get_math_variants (void) const + { return this+mathVariants; } +#endif + + protected: + FixedVersion<>version; /* Version of the fvar table + * initially set to 0x00010000u */ + Offset<> things; /* Offset in bytes from the beginning of the table + * to the start of the AxisRecord array. */ + USHORT reserved; /* This field is permanently reserved. Set to 2. */ + USHORT axisCount; /* The number of variation axes in the font (the + * number of records in the axes array). */ + USHORT axisSize; /* The size in bytes of each VariationAxisRecord — + * set to 20 (0x0014) for this version. */ + USHORT instanceCount; /* The number of named instances defined in the font + * (the number of records in the instances array). */ + USHORT instanceSize; /* The size in bytes of each InstanceRecord — set + * to either axisCount * sizeof(Fixed) + 4, or to + * axisCount * sizeof(Fixed) + 6. */ + + public: + DEFINE_SIZE_STATIC (16); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_FVAR_TABLE_HH */ diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc new file mode 100644 index 000000000..c9dcb1f7b --- /dev/null +++ b/src/hb-ot-var.cc @@ -0,0 +1,63 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-open-type-private.hh" + +#include "hb-ot-layout-private.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var.h" + +HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) + +static inline const OT::fvar& +_get_fvar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar); + + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + + return *(layout->fvar.get ()); +} + +/* + * OT::fvar + */ + +/** + * hb_ot_var_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of OpenType variation data on the face. + * + * Return value: true if face has a `fvar' table and false otherwise + * + * Since: 1.4.2 + **/ +hb_bool_t +hb_ot_var_has_data (hb_face_t *face) +{ + return &_get_fvar (face) != &OT::Null(OT::fvar); +} diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h new file mode 100644 index 000000000..679feb949 --- /dev/null +++ b/src/hb-ot-var.h @@ -0,0 +1,81 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_VAR_H +#define HB_OT_VAR_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +#define HB_OT_TAG_fvar HB_TAG('f','v','a','r') +#define HB_OT_TAG_avar HB_TAG('a','v','a','r') + + +/* + * fvar / avar + */ + +/** + * hb_ot_var_axis_t: + * + * Since: 1.4.2 + */ +typedef struct hb_ot_var_axis_t { + hb_tag_t tag; + unsigned int name_id; + double min_value; + double def_value; + double max_value; +} hb_ot_var_axis_t; + +HB_EXTERN hb_bool_t +hb_ot_var_has_data (hb_face_t *face); + +#if 0 + +HB_EXTERN unsigned int +Xhb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */); + +/* TODO Add "find_axis", etc API? Are they needed at all? */ + +HB_EXTERN unsigned int +Xhb_ot_var_get_named_instances (hb_face_t *face, ... ); + +#endif + + +HB_END_DECLS + +#endif /* HB_OT_VAR_H */ diff --git a/src/hb-ot.h b/src/hb-ot.h index 113e37b08..2120a3efa 100644 --- a/src/hb-ot.h +++ b/src/hb-ot.h @@ -35,6 +35,7 @@ #include "hb-ot-math.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" +#include "hb-ot-var.h" HB_BEGIN_DECLS From 469926cc45760cb681d44e5757b18b9bdd736189 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 17:40:46 -0800 Subject: [PATCH 0200/1326] [var] Change double to float in API --- src/hb-ot-var.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index 679feb949..9d73bed49 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -52,9 +52,9 @@ HB_BEGIN_DECLS typedef struct hb_ot_var_axis_t { hb_tag_t tag; unsigned int name_id; - double min_value; - double def_value; - double max_value; + float min_value; + float def_value; + float max_value; } hb_ot_var_axis_t; HB_EXTERN hb_bool_t From f2e73d37e77ccea8b948d1ecf5f11e7a699386dc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 17:42:18 -0800 Subject: [PATCH 0201/1326] [var] Remove over-optimization --- src/hb-font.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 2935c4b4f..b91a35b67 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1552,10 +1552,6 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (font->immutable) return; - /* Skip tail zero entries. */ - while (coords_length && !coords[coords_length - 1]) - coords_length--; - int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL; if (unlikely (coords_length && !copy)) return; From b8376b10904e1772b8d34d852d1100ca7e2185e2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 18:19:28 -0800 Subject: [PATCH 0202/1326] Minor --- src/hb-ft.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index f127066a6..d5f8d5295 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -625,7 +625,7 @@ hb_ft_font_create (FT_Face ft_face, int hbCoords[mm_var->num_axis]; if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords)) { - for (int i = 0; i < mm_var->num_axis; ++i) + for (unsigned int i = 0; i < mm_var->num_axis; ++i) hbCoords[i] = coords[i] >> 2; hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis); From 422c0c36c80145a2d993f80d5c7d3265e3d8357a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 19:14:54 -0800 Subject: [PATCH 0203/1326] [var] Flesh out a bit --- src/hb-ot-var-fvar-table.hh | 72 +++++++++++++++++++++++++++++-------- src/hb-ot-var.h | 10 +++++- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index 84617411c..39015b331 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -63,7 +63,7 @@ struct AxisRecord return_trace (c->check_struct (this)); } - protected: + public: Tag axisTag; /* Tag identifying the design variation for the axis. */ Fixed minValue; /* The minimum coordinate value for the axis. */ Fixed defaultValue; /* The default coordinate value for the axis. */ @@ -89,23 +89,67 @@ struct fvar { TRACE_SANITIZE (this); return_trace (version.sanitize (c) && - likely (version.major == 1) /*&& - mathConstants.sanitize (c, this) && - mathGlyphInfo.sanitize (c, this) && - mathVariants.sanitize (c, this)*/); + likely (version.major == 1) && + c->check_struct (this) && + instanceSize >= axisCount * 4 + 4 && + axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + c->check_range (this, things) && + c->check_range (&StructAtOffset (this, things), + axisCount * axisSize + instanceCount * instanceSize)); } -#if 0 - inline hb_position_t get_constant (hb_ot_math_constant_t constant, - hb_font_t *font) const - { return (this+mathConstants).get_value (constant, font); } + inline const AxisRecord * get_axes (void) const + { return &StructAtOffset (this, things); } - inline const MathGlyphInfo &get_math_glyph_info (void) const - { return this+mathGlyphInfo; } + inline const InstanceRecord * get_instances (void) const + { return &StructAtOffset (get_axes () + axisCount, 0); } - inline const MathVariants &get_math_variants (void) const - { return this+mathVariants; } -#endif + inline unsigned int get_axis_count (void) const + { return axisCount; } + + inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const + { + const AxisRecord *axes = get_axes (); + unsigned int count = get_axis_count (); + for (unsigned int i = 0; i < count; i++) + if (axes[i].axisTag == tag) + { + if (index) + *index = i; + if (info) + { + const AxisRecord &axis = axes[i]; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN (info->default_value, axis.minValue / 65536.); + info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + } + return true; + } + if (index) + *index = HB_OT_VAR_NO_AXIS_INDEX; + return false; + } + + inline int normalize_axis_value (hb_tag_t tag, float v, unsigned int *axis_index) const + { + hb_ot_var_axis_t axis; + if (!find_axis (tag, axis_index, &axis)) + return 0; + + v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ + + if (v == axis.default_value) + return 0; + else if (v < axis.default_value) + v = (v - axis.default_value) / (axis.default_value - axis.min_value); + else + v = (v - axis.default_value) / (axis.max_value - axis.default_value); + return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); + } protected: FixedVersion<>version; /* Version of the fvar table diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index 9d73bed49..fd7a5aaf0 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -53,15 +53,23 @@ typedef struct hb_ot_var_axis_t { hb_tag_t tag; unsigned int name_id; float min_value; - float def_value; + float default_value; float max_value; } hb_ot_var_axis_t; HB_EXTERN hb_bool_t hb_ot_var_has_data (hb_face_t *face); +#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu + #if 0 +HB_EXTERN hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info); + HB_EXTERN unsigned int Xhb_ot_var_get_axes (hb_face_t *face, unsigned int start_offset, From 785982bf830723552270db5649abcb9f9f0b46b1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 19:57:27 -0800 Subject: [PATCH 0204/1326] [var] Flesh out some more --- src/Makefile.am | 2 ++ src/hb-ot-var-fvar-table.hh | 69 +++++++++++++++++++++++++++---------- src/hb-ot-var.cc | 39 ++++++++++++++++++++- src/hb-ot-var.h | 21 +++++++---- 4 files changed, 104 insertions(+), 27 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 8cfe4ac7c..d7420a090 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -299,6 +299,8 @@ test_buffer_serialize_SOURCES = test-buffer-serialize.cc test_buffer_serialize_CPPFLAGS = $(HBCFLAGS) test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS) +check: harfbuzz.def # For check-defs.sh + dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ check-defs.sh \ diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index 39015b331..cb88de883 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -99,15 +99,49 @@ struct fvar axisCount * axisSize + instanceCount * instanceSize)); } - inline const AxisRecord * get_axes (void) const - { return &StructAtOffset (this, things); } - - inline const InstanceRecord * get_instances (void) const - { return &StructAtOffset (get_axes () + axisCount, 0); } - inline unsigned int get_axis_count (void) const { return axisCount; } + inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const + { + if (unlikely (index >= axisCount)) + return false; + + if (info) + { + const AxisRecord &axis = get_axes ()[index]; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN (info->default_value, axis.minValue / 65536.); + info->max_value = MAX (info->default_value, axis.maxValue / 65536.); + } + + return true; + } + + inline unsigned int get_axis_infos (unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) const + { + if (axes_count) + { + unsigned int count = axisCount; + start_offset = MIN (start_offset, count); + + count -= start_offset; + axes_array += start_offset; + + count = MIN (count, *axes_count); + *axes_count = count; + + for (unsigned int i = 0; i < count; i++) + get_axis (start_offset + i, axes_array + i); + } + return axisCount; + } + inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const { const AxisRecord *axes = get_axes (); @@ -117,27 +151,17 @@ struct fvar { if (index) *index = i; - if (info) - { - const AxisRecord &axis = axes[i]; - info->tag = axis.axisTag; - info->name_id = axis.axisNameID; - info->default_value = axis.defaultValue / 65536.; - /* Ensure order, to simplify client math. */ - info->min_value = MIN (info->default_value, axis.minValue / 65536.); - info->max_value = MAX (info->default_value, axis.maxValue / 65536.); - } - return true; + return get_axis (i, info); } if (index) *index = HB_OT_VAR_NO_AXIS_INDEX; return false; } - inline int normalize_axis_value (hb_tag_t tag, float v, unsigned int *axis_index) const + inline int normalize_axis_value (unsigned int axis_index, float v) const { hb_ot_var_axis_t axis; - if (!find_axis (tag, axis_index, &axis)) + if (!get_axis (axis_index, &axis)) return 0; v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ @@ -151,6 +175,13 @@ struct fvar return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); } + protected: + inline const AxisRecord * get_axes (void) const + { return &StructAtOffset (this, things); } + + inline const InstanceRecord * get_instances (void) const + { return &StructAtOffset (get_axes () + axisCount, 0); } + protected: FixedVersion<>version; /* Version of the fvar table * initially set to 0x00010000u */ diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index c9dcb1f7b..d1e97257c 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -43,7 +43,7 @@ _get_fvar (hb_face_t *face) } /* - * OT::fvar + * fvar/avar */ /** @@ -51,6 +51,7 @@ _get_fvar (hb_face_t *face) * @face: #hb_face_t to test * * This function allows to verify the presence of OpenType variation data on the face. + * Alternatively, use hb_ot_var_get_axis_count(). * * Return value: true if face has a `fvar' table and false otherwise * @@ -61,3 +62,39 @@ hb_ot_var_has_data (hb_face_t *face) { return &_get_fvar (face) != &OT::Null(OT::fvar); } + +unsigned int +hb_ot_var_get_axis_count (hb_face_t *face) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_count (); +} + +unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_infos (start_offset, axes_count, axes_array); +} + +HB_EXTERN hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.find_axis (axis_tag, axis_index, axis_info); +} + +HB_EXTERN int +hb_ot_var_normalize_axis_value (hb_face_t *face, + unsigned int axis_index, + float v) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.normalize_axis_value (axis_index, v); +} diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index fd7a5aaf0..4023b29f4 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -62,7 +62,14 @@ hb_ot_var_has_data (hb_face_t *face); #define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu -#if 0 +HB_EXTERN unsigned int +hb_ot_var_get_axis_count (hb_face_t *face); + +HB_EXTERN unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */); HB_EXTERN hb_bool_t hb_ot_var_find_axis (hb_face_t *face, @@ -70,13 +77,13 @@ hb_ot_var_find_axis (hb_face_t *face, unsigned int *axis_index, hb_ot_var_axis_t *axis_info); -HB_EXTERN unsigned int -Xhb_ot_var_get_axes (hb_face_t *face, - unsigned int start_offset, - unsigned int *axes_count /* IN/OUT */, - hb_ot_var_axis_t *axes_array /* OUT */); -/* TODO Add "find_axis", etc API? Are they needed at all? */ +HB_EXTERN int +hb_ot_var_normalize_axis_value (hb_face_t *face, + unsigned int axis_index, + float v); + +#if 0 HB_EXTERN unsigned int Xhb_ot_var_get_named_instances (hb_face_t *face, ... ); From 72364103bc9d910d19f23a3764d045af79d076d5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 20:16:53 -0800 Subject: [PATCH 0205/1326] Move code around --- src/hb-common.cc | 250 +++++++++++++++++++++++++++++++++++++++++++++++ src/hb-common.h | 18 ++++ src/hb-shape.cc | 248 ---------------------------------------------- src/hb-shape.h | 16 --- 4 files changed, 268 insertions(+), 264 deletions(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index 3564e4355..04d9fb09a 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -605,3 +605,253 @@ hb_version_atleast (unsigned int major, { return HB_VERSION_ATLEAST (major, minor, micro); } + + +/* hb_feature_t */ + +static bool +parse_space (const char **pp, const char *end) +{ + while (*pp < end && ISSPACE (**pp)) + (*pp)++; + return true; +} + +static bool +parse_char (const char **pp, const char *end, char c) +{ + parse_space (pp, end); + + if (*pp == end || **pp != c) + return false; + + (*pp)++; + return true; +} + +static bool +parse_uint (const char **pp, const char *end, unsigned int *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + /* Intentionally use strtol instead of strtoul, such that + * -1 turns into "big number"... */ + errno = 0; + v = strtol (p, &pend, 0); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_bool (const char **pp, const char *end, unsigned int *pv) +{ + parse_space (pp, end); + + const char *p = *pp; + while (*pp < end && ISALPHA(**pp)) + (*pp)++; + + /* CSS allows on/off as aliases 1/0. */ + if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) + *pv = 1; + else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) + *pv = 0; + else + return false; + + return true; +} + +static bool +parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) +{ + if (parse_char (pp, end, '-')) + feature->value = 0; + else { + parse_char (pp, end, '+'); + feature->value = 1; + } + + return true; +} + +static bool +parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) +{ + parse_space (pp, end); + + char quote = 0; + + if (*pp < end && (**pp == '\'' || **pp == '"')) + { + quote = **pp; + (*pp)++; + } + + const char *p = *pp; + while (*pp < end && ISALNUM(**pp)) + (*pp)++; + + if (p == *pp || *pp - p > 4) + return false; + + feature->tag = hb_tag_from_string (p, *pp - p); + + if (quote) + { + /* CSS expects exactly four bytes. And we only allow quotations for + * CSS compatibility. So, enforce the length. */ + if (*pp - p != 4) + return false; + if (*pp == end || **pp != quote) + return false; + (*pp)++; + } + + return true; +} + +static bool +parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) +{ + parse_space (pp, end); + + bool has_start; + + feature->start = 0; + feature->end = (unsigned int) -1; + + if (!parse_char (pp, end, '[')) + return true; + + has_start = parse_uint (pp, end, &feature->start); + + if (parse_char (pp, end, ':')) { + parse_uint (pp, end, &feature->end); + } else { + if (has_start) + feature->end = feature->start + 1; + } + + return parse_char (pp, end, ']'); +} + +static bool +parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) +{ + bool had_equal = parse_char (pp, end, '='); + bool had_value = parse_uint (pp, end, &feature->value) || + parse_bool (pp, end, &feature->value); + /* CSS doesn't use equal-sign between tag and value. + * If there was an equal-sign, then there *must* be a value. + * A value without an eqaul-sign is ok, but not required. */ + return !had_equal || had_value; +} + + +static bool +parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) +{ + return parse_feature_value_prefix (pp, end, feature) && + parse_feature_tag (pp, end, feature) && + parse_feature_indices (pp, end, feature) && + parse_feature_value_postfix (pp, end, feature) && + parse_space (pp, end) && + *pp == end; +} + +/** + * hb_feature_from_string: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated + * @feature: (out): the #hb_feature_t to initialize with the parsed values + * + * Parses a string into a #hb_feature_t. + * + * TODO: document the syntax here. + * + * Return value: + * %true if @str is successfully parsed, %false otherwise. + * + * Since: 0.9.5 + **/ +hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature) +{ + hb_feature_t feat; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_feature (&str, str + len, &feat))) + { + if (feature) + *feature = feat; + return true; + } + + if (feature) + memset (feature, 0, sizeof (*feature)); + return false; +} + +/** + * hb_feature_to_string: + * @feature: an #hb_feature_t to convert + * @buf: (array length=size) (out): output string + * @size: the allocated size of @buf + * + * Converts a #hb_feature_t into a %NULL-terminated string in the format + * understood by hb_feature_from_string(). The client in responsible for + * allocating big enough size for @buf, 128 bytes is more than enough. + * + * Since: 0.9.5 + **/ +void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + if (feature->value == 0) + s[len++] = '-'; + hb_tag_to_string (feature->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + if (feature->start != 0 || feature->end != (unsigned int) -1) + { + s[len++] = '['; + if (feature->start) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); + if (feature->end != feature->start + 1) { + s[len++] = ':'; + if (feature->end != (unsigned int) -1) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); + } + s[len++] = ']'; + } + if (feature->value > 1) + { + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); + } + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} diff --git a/src/hb-common.h b/src/hb-common.h index 2cbee76a8..dd72a9dd2 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -362,6 +362,24 @@ typedef struct hb_user_data_key_t { typedef void (*hb_destroy_func_t) (void *user_data); +/* Font features. */ + +typedef struct hb_feature_t { + hb_tag_t tag; + uint32_t value; + unsigned int start; + unsigned int end; +} hb_feature_t; + +HB_EXTERN hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +HB_EXTERN void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + + HB_END_DECLS #endif /* HB_COMMON_H */ diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 706f14420..f57cad903 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -45,254 +45,6 @@ * contains the output glyphs and their positions. **/ -static bool -parse_space (const char **pp, const char *end) -{ - while (*pp < end && ISSPACE (**pp)) - (*pp)++; - return true; -} - -static bool -parse_char (const char **pp, const char *end, char c) -{ - parse_space (pp, end); - - if (*pp == end || **pp != c) - return false; - - (*pp)++; - return true; -} - -static bool -parse_uint (const char **pp, const char *end, unsigned int *pv) -{ - char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); - strncpy (buf, *pp, len); - buf[len] = '\0'; - - char *p = buf; - char *pend = p; - unsigned int v; - - /* Intentionally use strtol instead of strtoul, such that - * -1 turns into "big number"... */ - errno = 0; - v = strtol (p, &pend, 0); - if (errno || p == pend) - return false; - - *pv = v; - *pp += pend - p; - return true; -} - -static bool -parse_bool (const char **pp, const char *end, unsigned int *pv) -{ - parse_space (pp, end); - - const char *p = *pp; - while (*pp < end && ISALPHA(**pp)) - (*pp)++; - - /* CSS allows on/off as aliases 1/0. */ - if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) - *pv = 1; - else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) - *pv = 0; - else - return false; - - return true; -} - -static bool -parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) -{ - if (parse_char (pp, end, '-')) - feature->value = 0; - else { - parse_char (pp, end, '+'); - feature->value = 1; - } - - return true; -} - -static bool -parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - char quote = 0; - - if (*pp < end && (**pp == '\'' || **pp == '"')) - { - quote = **pp; - (*pp)++; - } - - const char *p = *pp; - while (*pp < end && ISALNUM(**pp)) - (*pp)++; - - if (p == *pp || *pp - p > 4) - return false; - - feature->tag = hb_tag_from_string (p, *pp - p); - - if (quote) - { - /* CSS expects exactly four bytes. And we only allow quotations for - * CSS compatibility. So, enforce the length. */ - if (*pp - p != 4) - return false; - if (*pp == end || **pp != quote) - return false; - (*pp)++; - } - - return true; -} - -static bool -parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - bool has_start; - - feature->start = 0; - feature->end = (unsigned int) -1; - - if (!parse_char (pp, end, '[')) - return true; - - has_start = parse_uint (pp, end, &feature->start); - - if (parse_char (pp, end, ':')) { - parse_uint (pp, end, &feature->end); - } else { - if (has_start) - feature->end = feature->start + 1; - } - - return parse_char (pp, end, ']'); -} - -static bool -parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) -{ - bool had_equal = parse_char (pp, end, '='); - bool had_value = parse_uint (pp, end, &feature->value) || - parse_bool (pp, end, &feature->value); - /* CSS doesn't use equal-sign between tag and value. - * If there was an equal-sign, then there *must* be a value. - * A value without an eqaul-sign is ok, but not required. */ - return !had_equal || had_value; -} - - -static bool -parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) -{ - return parse_feature_value_prefix (pp, end, feature) && - parse_feature_tag (pp, end, feature) && - parse_feature_indices (pp, end, feature) && - parse_feature_value_postfix (pp, end, feature) && - parse_space (pp, end) && - *pp == end; -} - -/** - * hb_feature_from_string: - * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is %NULL terminated - * @feature: (out): the #hb_feature_t to initialize with the parsed values - * - * Parses a string into a #hb_feature_t. - * - * TODO: document the syntax here. - * - * Return value: - * %true if @str is successfully parsed, %false otherwise. - * - * Since: 0.9.5 - **/ -hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature) -{ - hb_feature_t feat; - - if (len < 0) - len = strlen (str); - - if (likely (parse_one_feature (&str, str + len, &feat))) - { - if (feature) - *feature = feat; - return true; - } - - if (feature) - memset (feature, 0, sizeof (*feature)); - return false; -} - -/** - * hb_feature_to_string: - * @feature: an #hb_feature_t to convert - * @buf: (array length=size) (out): output string - * @size: the allocated size of @buf - * - * Converts a #hb_feature_t into a %NULL-terminated string in the format - * understood by hb_feature_from_string(). The client in responsible for - * allocating big enough size for @buf, 128 bytes is more than enough. - * - * Since: 0.9.5 - **/ -void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size) -{ - if (unlikely (!size)) return; - - char s[128]; - unsigned int len = 0; - if (feature->value == 0) - s[len++] = '-'; - hb_tag_to_string (feature->tag, s + len); - len += 4; - while (len && s[len - 1] == ' ') - len--; - if (feature->start != 0 || feature->end != (unsigned int) -1) - { - s[len++] = '['; - if (feature->start) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); - if (feature->end != feature->start + 1) { - s[len++] = ':'; - if (feature->end != (unsigned int) -1) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); - } - s[len++] = ']'; - } - if (feature->value > 1) - { - s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); - } - assert (len < ARRAY_LENGTH (s)); - len = MIN (len, size - 1); - memcpy (buf, s, len); - buf[len] = '\0'; -} - - static const char **static_shaper_list; #ifdef HB_USE_ATEXIT diff --git a/src/hb-shape.h b/src/hb-shape.h index 53bb845bf..39507ff74 100644 --- a/src/hb-shape.h +++ b/src/hb-shape.h @@ -40,22 +40,6 @@ HB_BEGIN_DECLS -typedef struct hb_feature_t { - hb_tag_t tag; - uint32_t value; - unsigned int start; - unsigned int end; -} hb_feature_t; - -HB_EXTERN hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature); - -HB_EXTERN void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size); - - HB_EXTERN void hb_shape (hb_font_t *font, hb_buffer_t *buffer, From b3c0714b4bbb726b2b3e5e0416ac84cb5c6eb34e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 20 Jan 2017 20:30:03 -0800 Subject: [PATCH 0206/1326] [var] Add hb_var_coord_t and parsing routines --- src/hb-common.cc | 94 +++++++++++++++++++++++++++++++++++++++++++++--- src/hb-common.h | 15 +++++++- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index 04d9fb09a..25c979c59 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -607,7 +607,8 @@ hb_version_atleast (unsigned int major, } -/* hb_feature_t */ + +/* hb_feature_t and hb_var_coord_t */ static bool parse_space (const char **pp, const char *end) @@ -653,6 +654,28 @@ parse_uint (const char **pp, const char *end, unsigned int *pv) return true; } +static bool +parse_float (const char **pp, const char *end, float *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + float v; + + errno = 0; + v = strtof (p, &pend); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + static bool parse_bool (const char **pp, const char *end, unsigned int *pv) { @@ -673,6 +696,8 @@ parse_bool (const char **pp, const char *end, unsigned int *pv) return true; } +/* hb_feature_t */ + static bool parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) { @@ -687,7 +712,7 @@ parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feat } static bool -parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) +parse_tag (const char **pp, const char *end, hb_tag_t *tag) { parse_space (pp, end); @@ -706,7 +731,7 @@ parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) if (p == *pp || *pp - p > 4) return false; - feature->tag = hb_tag_from_string (p, *pp - p); + *tag = hb_tag_from_string (p, *pp - p); if (quote) { @@ -759,12 +784,11 @@ parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *fea return !had_equal || had_value; } - static bool parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) { return parse_feature_value_prefix (pp, end, feature) && - parse_feature_tag (pp, end, feature) && + parse_tag (pp, end, &feature->tag) && parse_feature_indices (pp, end, feature) && parse_feature_value_postfix (pp, end, feature) && parse_space (pp, end) && @@ -855,3 +879,63 @@ hb_feature_to_string (hb_feature_t *feature, memcpy (buf, s, len); buf[len] = '\0'; } + +/* hb_var_coord_t */ + +static bool +parse_var_coord_value (const char **pp, const char *end, hb_var_coord_t *var_coord) +{ + parse_char (pp, end, '='); /* Optional. */ + return parse_float (pp, end, &var_coord->value); +} + +static bool +parse_one_var_coord (const char **pp, const char *end, hb_var_coord_t *var_coord) +{ + return parse_tag (pp, end, &var_coord->tag) && + parse_var_coord_value (pp, end, var_coord) && + parse_space (pp, end) && + *pp == end; +} + +hb_bool_t +hb_var_coord_from_string (const char *str, int len, + hb_var_coord_t *var_coord) +{ + hb_var_coord_t coord; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_var_coord (&str, str + len, &coord))) + { + if (var_coord) + *var_coord = coord; + return true; + } + + if (var_coord) + memset (var_coord, 0, sizeof (*var_coord)); + return false; +} + +void +hb_var_coord_to_string (hb_var_coord_t *var_coord, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + hb_tag_to_string (var_coord->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", var_coord->value)); + + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} diff --git a/src/hb-common.h b/src/hb-common.h index dd72a9dd2..e483fb857 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -362,7 +362,7 @@ typedef struct hb_user_data_key_t { typedef void (*hb_destroy_func_t) (void *user_data); -/* Font features. */ +/* Font features and variations. */ typedef struct hb_feature_t { hb_tag_t tag; @@ -379,6 +379,19 @@ HB_EXTERN void hb_feature_to_string (hb_feature_t *feature, char *buf, unsigned int size); +typedef struct hb_var_coord_t { + hb_tag_t tag; + float value; +} hb_var_coord_t; + +HB_EXTERN hb_bool_t +hb_var_coord_from_string (const char *str, int len, + hb_var_coord_t *var_coord); + +HB_EXTERN void +hb_var_coord_to_string (hb_var_coord_t *var_coord, + char *buf, unsigned int size); + HB_END_DECLS From bf0d3a665baac9e33c0f774b22197c321b864c80 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 14:48:46 -0800 Subject: [PATCH 0207/1326] [var] Add hb_font_get_var_coords_normalized() --- src/hb-font.cc | 10 ++++++++++ src/hb-font.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index b91a35b67..a8b9e4c3b 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1565,6 +1565,16 @@ hb_font_set_var_coords_normalized (hb_font_t *font, font->num_coords = coords_length; } +int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length) +{ + if (length) + *length = font->coords_length; + + return font->coords; +} + #ifndef HB_DISABLE_DEPRECATED diff --git a/src/hb-font.h b/src/hb-font.h index 881328672..5f22331b6 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -609,6 +609,10 @@ hb_font_set_var_coords_normalized (hb_font_t *font, int *coords, /* XXX 2.14 normalized */ unsigned int coords_length); +HB_EXTERN int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length); + HB_END_DECLS #endif /* HB_FONT_H */ From 0dcc7b49a830e2680d3e6d86d953efab85cef6ff Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 14:50:22 -0800 Subject: [PATCH 0208/1326] [var] Minor lifecycle adjustment --- src/hb-font.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index a8b9e4c3b..e2a0a5f0f 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1556,11 +1556,11 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (unlikely (coords_length && !copy)) return; - free (font->coords); - if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); + free (font->coords); + font->coords = copy; font->num_coords = coords_length; } From 8b2a58047095604dcdc576ecbe3e8c2ebb8f48f0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 15:05:00 -0800 Subject: [PATCH 0209/1326] [var] Add hb_font_set_var_coords_design() --- src/hb-font.cc | 21 +++++++++++++++++++-- src/hb-font.h | 7 ++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index e2a0a5f0f..e7f57529d 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1543,10 +1543,27 @@ hb_font_get_ppem (hb_font_t *font, if (y_ppem) *y_ppem = font->y_ppem; } +/* + * Variations + */ + +void +hb_font_set_var_coords_design (hb_font_t *font, + float *coords, + unsigned int coords_length) +{ + int normalized[coords_length]; // XXX Remove variable-length array use... + + hb_face_t *face = font->face; + for (unsigned int i = 0; i < coords_length; i++) + normalized[i] = hb_ot_var_normalize_axis_value (face, i, coords[i]); + + hb_font_set_var_coords_normalized (font, normalized, coords_length); +} void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* XXX 2.14 normalized */ + int *coords, /* 2.14 normalized */ unsigned int coords_length) { if (font->immutable) @@ -1570,7 +1587,7 @@ hb_font_get_var_coords_normalized (hb_font_t *font, unsigned int *length) { if (length) - *length = font->coords_length; + *length = font->num_coords; return font->coords; } diff --git a/src/hb-font.h b/src/hb-font.h index 5f22331b6..31e5971b1 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -604,9 +604,14 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *y_ppem); +HB_EXTERN void +hb_font_set_var_coords_design (hb_font_t *font, + float *coords, + unsigned int coords_length); + HB_EXTERN void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* XXX 2.14 normalized */ + int *coords, /* 2.14 normalized */ unsigned int coords_length); HB_EXTERN int * From 2d40923ca914c90304d07d6e7b9b1040c79c76fe Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 15:06:15 -0800 Subject: [PATCH 0210/1326] Minor --- src/hb-ot-math.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index ec8df2c25..eb08badbd 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -120,7 +120,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, /** * hb_ot_math_is_glyph_extended_shape: - * @font: a #hb_font_t to test + * @face: a #hb_face_t to test * @glyph: a glyph index to test * * Return value: true if the glyph is an extended shape, false otherwise From 113393efec5e0c4c10c141a6d4b801d50fcd8ab8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 15:12:03 -0800 Subject: [PATCH 0211/1326] Remove a few unused includes --- src/hb-face.cc | 6 +----- src/hb-font.cc | 7 ------- src/hb-ot-layout.cc | 5 +---- src/hb-ot-tag.cc | 3 --- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/hb-face.cc b/src/hb-face.cc index 6b563bc8f..1ba970707 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -28,15 +28,11 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - -#include "hb-font-private.hh" +#include "hb-face-private.hh" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" -#include - /* * hb_face_t diff --git a/src/hb-font.cc b/src/hb-font.cc index e7f57529d..08c00bfc0 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -28,14 +28,7 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - #include "hb-font-private.hh" -#include "hb-open-file-private.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-maxp-table.hh" - -#include /* diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index d8d628480..d7ededd8d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -34,13 +34,10 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-jstf-table.hh" +#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-map-private.hh" -#include -#include - HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 5c348e898..9b0db507b 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -28,9 +28,6 @@ #include "hb-private.hh" -#include - - /* hb_script_t */ From 2491134b386507f611a47e43e3f7c2766d0d288b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 15:21:50 -0800 Subject: [PATCH 0212/1326] [var] Add hb_font_set_var_coords() --- src/hb-font.cc | 38 ++++++++++++++++++++++++++++++++++++-- src/hb-font.h | 8 ++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 08c00bfc0..1b4ed7e24 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1540,11 +1540,45 @@ hb_font_get_ppem (hb_font_t *font, * Variations */ +void +hb_font_set_var_coords (hb_font_t *font, + const hb_var_coord_t *coords, + unsigned int coords_length) +{ + if (font->immutable) + return; + + if (!coords_length) + { + hb_font_set_var_coords_normalized (font, NULL, 0); + return; + } + + hb_face_t *face = font->face; + + unsigned int length = hb_ot_var_get_axis_count (face); + int normalized[length]; // XXX Remove variable-length array use... + + memset (normalized, 0, length * sizeof (normalized[0])); + + for (unsigned int i = 0; i < coords_length; i++) + { + unsigned int axis_index; + if (hb_ot_var_find_axis (face, coords[i].tag, &axis_index, NULL)) + normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, coords[i].value); + } + + hb_font_set_var_coords_normalized (font, normalized, coords_length); +} + void hb_font_set_var_coords_design (hb_font_t *font, - float *coords, + const float *coords, unsigned int coords_length) { + if (font->immutable) + return; + int normalized[coords_length]; // XXX Remove variable-length array use... hb_face_t *face = font->face; @@ -1556,7 +1590,7 @@ hb_font_set_var_coords_design (hb_font_t *font, void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* 2.14 normalized */ + const int *coords, /* 2.14 normalized */ unsigned int coords_length) { if (font->immutable) diff --git a/src/hb-font.h b/src/hb-font.h index 31e5971b1..83eb68c98 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -603,15 +603,19 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, unsigned int *y_ppem); +HB_EXTERN void +hb_font_set_var_coords (hb_font_t *font, + const hb_var_coord_t *coords, + unsigned int coords_length); HB_EXTERN void hb_font_set_var_coords_design (hb_font_t *font, - float *coords, + const float *coords, unsigned int coords_length); HB_EXTERN void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* 2.14 normalized */ + const int *coords, /* 2.14 normalized */ unsigned int coords_length); HB_EXTERN int * From 64fe92bf2d43a0ea31743d774e073f202021dbd1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 15:36:35 -0800 Subject: [PATCH 0213/1326] [var] Remove use of variable-length arrays --- src/hb-font.cc | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 1b4ed7e24..39d176914 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1540,6 +1540,17 @@ hb_font_get_ppem (hb_font_t *font, * Variations */ +static void +_hb_font_adopt_var_coords_normalized (hb_font_t *font, + int *coords, /* 2.14 normalized */ + unsigned int coords_length) +{ + free (font->coords); + + font->coords = coords; + font->num_coords = coords_length; +} + void hb_font_set_var_coords (hb_font_t *font, const hb_var_coord_t *coords, @@ -1557,10 +1568,12 @@ hb_font_set_var_coords (hb_font_t *font, hb_face_t *face = font->face; unsigned int length = hb_ot_var_get_axis_count (face); - int normalized[length]; // XXX Remove variable-length array use... - memset (normalized, 0, length * sizeof (normalized[0])); + int *normalized = length ? (int *) calloc (length, sizeof (int)) : NULL; + if (unlikely (length && !normalized)) + return; + /* normalized is filled with zero already. */ for (unsigned int i = 0; i < coords_length; i++) { unsigned int axis_index; @@ -1568,7 +1581,7 @@ hb_font_set_var_coords (hb_font_t *font, normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, coords[i].value); } - hb_font_set_var_coords_normalized (font, normalized, coords_length); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } void @@ -1579,13 +1592,15 @@ hb_font_set_var_coords_design (hb_font_t *font, if (font->immutable) return; - int normalized[coords_length]; // XXX Remove variable-length array use... + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL; + if (unlikely (coords_length && !normalized)) + return; hb_face_t *face = font->face; for (unsigned int i = 0; i < coords_length; i++) normalized[i] = hb_ot_var_normalize_axis_value (face, i, coords[i]); - hb_font_set_var_coords_normalized (font, normalized, coords_length); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } void @@ -1603,10 +1618,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); - free (font->coords); - - font->coords = copy; - font->num_coords = coords_length; + _hb_font_adopt_var_coords_normalized (font, copy, coords_length); } int * From bb1e19268f02d4aad2240c52852e72afcf0f79ad Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 17:41:37 -0800 Subject: [PATCH 0214/1326] [var] Rename var_coord to variation Looks much better. --- src/hb-common.cc | 36 ++++++++++++++++++------------------ src/hb-common.h | 10 +++++----- src/hb-font.cc | 20 ++++++++++---------- src/hb-font.h | 6 +++--- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index 25c979c59..a804f822b 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -608,7 +608,7 @@ hb_version_atleast (unsigned int major, -/* hb_feature_t and hb_var_coord_t */ +/* hb_feature_t and hb_variation_t */ static bool parse_space (const char **pp, const char *end) @@ -880,59 +880,59 @@ hb_feature_to_string (hb_feature_t *feature, buf[len] = '\0'; } -/* hb_var_coord_t */ +/* hb_variation_t */ static bool -parse_var_coord_value (const char **pp, const char *end, hb_var_coord_t *var_coord) +parse_variation_value (const char **pp, const char *end, hb_variation_t *variation) { parse_char (pp, end, '='); /* Optional. */ - return parse_float (pp, end, &var_coord->value); + return parse_float (pp, end, &variation->value); } static bool -parse_one_var_coord (const char **pp, const char *end, hb_var_coord_t *var_coord) +parse_one_variation (const char **pp, const char *end, hb_variation_t *variation) { - return parse_tag (pp, end, &var_coord->tag) && - parse_var_coord_value (pp, end, var_coord) && + return parse_tag (pp, end, &variation->tag) && + parse_variation_value (pp, end, variation) && parse_space (pp, end) && *pp == end; } hb_bool_t -hb_var_coord_from_string (const char *str, int len, - hb_var_coord_t *var_coord) +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation) { - hb_var_coord_t coord; + hb_variation_t var; if (len < 0) len = strlen (str); - if (likely (parse_one_var_coord (&str, str + len, &coord))) + if (likely (parse_one_variation (&str, str + len, &var))) { - if (var_coord) - *var_coord = coord; + if (variation) + *variation = var; return true; } - if (var_coord) - memset (var_coord, 0, sizeof (*var_coord)); + if (variation) + memset (variation, 0, sizeof (*variation)); return false; } void -hb_var_coord_to_string (hb_var_coord_t *var_coord, +hb_variation_to_string (hb_variation_t *variation, char *buf, unsigned int size) { if (unlikely (!size)) return; char s[128]; unsigned int len = 0; - hb_tag_to_string (var_coord->tag, s + len); + hb_tag_to_string (variation->tag, s + len); len += 4; while (len && s[len - 1] == ' ') len--; s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", var_coord->value)); + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value)); assert (len < ARRAY_LENGTH (s)); len = MIN (len, size - 1); diff --git a/src/hb-common.h b/src/hb-common.h index e483fb857..ed0b97dfd 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -379,17 +379,17 @@ HB_EXTERN void hb_feature_to_string (hb_feature_t *feature, char *buf, unsigned int size); -typedef struct hb_var_coord_t { +typedef struct hb_variation_t { hb_tag_t tag; float value; -} hb_var_coord_t; +} hb_variation_t; HB_EXTERN hb_bool_t -hb_var_coord_from_string (const char *str, int len, - hb_var_coord_t *var_coord); +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation); HB_EXTERN void -hb_var_coord_to_string (hb_var_coord_t *var_coord, +hb_variation_to_string (hb_variation_t *variation, char *buf, unsigned int size); diff --git a/src/hb-font.cc b/src/hb-font.cc index 39d176914..607bd4893 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1552,14 +1552,14 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, } void -hb_font_set_var_coords (hb_font_t *font, - const hb_var_coord_t *coords, - unsigned int coords_length) +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length) { if (font->immutable) return; - if (!coords_length) + if (!variations_length) { hb_font_set_var_coords_normalized (font, NULL, 0); return; @@ -1567,18 +1567,18 @@ hb_font_set_var_coords (hb_font_t *font, hb_face_t *face = font->face; - unsigned int length = hb_ot_var_get_axis_count (face); + unsigned int coords_length = hb_ot_var_get_axis_count (face); - int *normalized = length ? (int *) calloc (length, sizeof (int)) : NULL; - if (unlikely (length && !normalized)) + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL; + if (unlikely (coords_length && !normalized)) return; /* normalized is filled with zero already. */ - for (unsigned int i = 0; i < coords_length; i++) + for (unsigned int i = 0; i < variations_length; i++) { unsigned int axis_index; - if (hb_ot_var_find_axis (face, coords[i].tag, &axis_index, NULL)) - normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, coords[i].value); + if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL)) + normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, variations[i].value); } _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); diff --git a/src/hb-font.h b/src/hb-font.h index 83eb68c98..fce4206df 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -604,9 +604,9 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *y_ppem); HB_EXTERN void -hb_font_set_var_coords (hb_font_t *font, - const hb_var_coord_t *coords, - unsigned int coords_length); +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length); HB_EXTERN void hb_font_set_var_coords_design (hb_font_t *font, From 111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 17:51:41 -0800 Subject: [PATCH 0215/1326] [util] Add --variations Is hooked up to the font, but not to FreeType, so raster doesn't show yet. Documentation needs to be done. --- util/options.cc | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ util/options.hh | 8 ++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/util/options.cc b/util/options.cc index bc699c1d1..8c79c4ad6 100644 --- a/util/options.cc +++ b/util/options.cc @@ -254,6 +254,47 @@ parse_features (const char *name G_GNUC_UNUSED, return true; } +static gboolean +parse_variations (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + char *s = (char *) arg; + char *p; + + font_opts->num_variations = 0; + g_free (font_opts->variations); + font_opts->variations = NULL; + + if (!*s) + return true; + + /* count the variations first, so we can allocate memory */ + p = s; + do { + font_opts->num_variations++; + p = strchr (p, ','); + if (p) + p++; + } while (p); + + font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations)); + + /* now do the actual parsing */ + p = s; + font_opts->num_variations = 0; + while (p && *p) { + char *end = strchr (p, ','); + if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations])) + font_opts->num_variations++; + p = end ? end + 1 : NULL; + } + + return true; +} + void view_options_t::add_options (option_parser_t *parser) @@ -415,6 +456,54 @@ font_options_t::add_options (option_parser_t *parser) "Font options:", "Options controlling the font", this); + + const gchar *variations_help = "Comma-separated list of font variations\n" + "\n" + " XXXXXXXXXXXXXXX\n" + " Features can be enabled or disabled, either globally or limited to\n" + " specific character ranges. The format for specifying feature settings\n" + " follows. All valid CSS font-feature-settings values other than 'normal'\n" + " and 'inherited' are also accepted, though, not documented below.\n" + "\n" + " The range indices refer to the positions between Unicode characters,\n" + " unless the --utf8-clusters is provided, in which case range indices\n" + " refer to UTF-8 byte indices. The position before the first character\n" + " is always 0.\n" + "\n" + " The format is Python-esque. Here is how it all works:\n" + "\n" + " Syntax: Value: Start: End:\n" + "\n" + " Setting value:\n" + " \"kern\" 1 0 ∞ # Turn feature on\n" + " \"+kern\" 1 0 ∞ # Turn feature on\n" + " \"-kern\" 0 0 ∞ # Turn feature off\n" + " \"kern=0\" 0 0 ∞ # Turn feature off\n" + " \"kern=1\" 1 0 ∞ # Turn feature on\n" + " \"aalt=2\" 2 0 ∞ # Choose 2nd alternate\n" + "\n" + " Setting index:\n" + " \"kern[]\" 1 0 ∞ # Turn feature on\n" + " \"kern[:]\" 1 0 ∞ # Turn feature on\n" + " \"kern[5:]\" 1 5 ∞ # Turn feature on, partial\n" + " \"kern[:5]\" 1 0 5 # Turn feature on, partial\n" + " \"kern[3:5]\" 1 3 5 # Turn feature on, range\n" + " \"kern[3]\" 1 3 3+1 # Turn feature on, single char\n" + "\n" + " Mixing it all:\n" + "\n" + " \"aalt[3:5]=2\" 2 3 5 # Turn 2nd alternate on for range"; + + GOptionEntry entries2[] = + { + {"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"}, + {NULL} + }; + parser->add_group (entries2, + "variations", + "Varitions options:", + "Options controlling font variations used", + this); } void @@ -561,6 +650,8 @@ font_options_t::get_font (void) const hb_font_set_scale (font, scale_x, scale_y); hb_face_destroy (face); + hb_font_set_variations (font, variations, num_variations); + void (*set_font_funcs) (hb_font_t *) = NULL; if (!font_funcs) { diff --git a/util/options.hh b/util/options.hh index 919e4f8b2..9ed4fd0e2 100644 --- a/util/options.hh +++ b/util/options.hh @@ -285,7 +285,10 @@ struct font_options_t : option_group_t { font_options_t (option_parser_t *parser, int default_font_size_, - unsigned int subpixel_bits_) { + unsigned int subpixel_bits_) + { + variations = NULL; + num_variations = 0; default_font_size = default_font_size_; subpixel_bits = subpixel_bits_; font_file = NULL; @@ -299,6 +302,7 @@ struct font_options_t : option_group_t } ~font_options_t (void) { g_free (font_file); + free (variations); g_free (font_funcs); hb_font_destroy (font); } @@ -309,6 +313,8 @@ struct font_options_t : option_group_t char *font_file; int face_index; + hb_variation_t *variations; + unsigned int num_variations; int default_font_size; unsigned int subpixel_bits; mutable double font_size_x; From 47ee34e84745756a9aaeb964772377b6c1417ed1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 21 Jan 2017 18:10:08 -0800 Subject: [PATCH 0216/1326] [var] Hook up variations to FreeType face hb-view correctly renders variations with ft font-funcs now. hb-ot-font needs HVAR implementation. --- src/hb-ft.cc | 10 ++++++++++ util/helper-cairo.cc | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index d5f8d5295..acb7bb1d0 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -736,6 +736,16 @@ hb_ft_font_set_funcs (hb_font_t *font) FT_Set_Transform (ft_face, &matrix, NULL); } + unsigned int num_coords; + int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + if (num_coords) + { + FT_Fixed ft_coords[num_coords]; + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] << 2; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + } + ft_face->generic.data = blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc index 8f30eea14..df5173b59 100644 --- a/util/helper-cairo.cc +++ b/util/helper-cairo.cc @@ -28,6 +28,7 @@ #include #include +#include FT_MULTIPLE_MASTERS_H #include "helper-cairo-ansi.hh" #ifdef CAIRO_HAS_SVG_SURFACE @@ -76,7 +77,8 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts) cairo_font_face_t *cairo_face; /* We cannot use the FT_Face from hb_font_t, as doing so will confuse hb_font_t because - * cairo will reset the face size. As such, create new face... */ + * cairo will reset the face size. As such, create new face... + * TODO Perhaps add API to hb-ft to encapsulate this code. */ FT_Face ft_face = NULL;//hb_ft_font_get_face (font); if (!ft_face) { @@ -100,7 +102,19 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts) CAIRO_FONT_WEIGHT_NORMAL); } else + { + unsigned int num_coords; + int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + if (num_coords) + { + FT_Fixed ft_coords[num_coords]; + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] << 2; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + } + cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); + } cairo_matrix_t ctm, font_matrix; cairo_font_options_t *font_options; From 825e40407da74576f8e83ce0bacad5b0459b83c8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 16:41:45 -0800 Subject: [PATCH 0217/1326] [hb-ft] Remove use of variable-length array Hopefully also fixes build failure on msvc. --- src/hb-ft.cc | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index acb7bb1d0..496fff230 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -621,17 +621,22 @@ hb_ft_font_create (FT_Face ft_face, FT_MM_Var *mm_var = NULL; if (!FT_Get_MM_Var (ft_face, &mm_var)) { - FT_Fixed coords[mm_var->num_axis]; - int hbCoords[mm_var->num_axis]; - if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords)) + FT_Fixed *ft_coords = (FT_Fixed *) calloc (mm_var->num_axis, sizeof (FT_Fixed)); + int *coords = (int *) calloc (mm_var->num_axis, sizeof (int)); + if (coords && ft_coords) { - for (unsigned int i = 0; i < mm_var->num_axis; ++i) - hbCoords[i] = coords[i] >> 2; + if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords)) + { + for (unsigned int i = 0; i < mm_var->num_axis; ++i) + coords[i] = ft_coords[i] >>= 2; - hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis); + hb_font_set_var_coords_normalized (font, coords, mm_var->num_axis); + } + free (coords); + free (ft_coords); } + free (mm_var); } - free (mm_var); #endif return font; @@ -740,10 +745,14 @@ hb_ft_font_set_funcs (hb_font_t *font) int *coords = hb_font_get_var_coords_normalized (font, &num_coords); if (num_coords) { - FT_Fixed ft_coords[num_coords]; - for (unsigned int i = 0; i < num_coords; i++) - ft_coords[i] = coords[i] << 2; - FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed)); + if (ft_coords) + { + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] << 2; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + free (ft_coords); + } } ft_face->generic.data = blob; From 5dfd341f51543279039ddafe883c0a1de205fb8a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 16:55:40 -0800 Subject: [PATCH 0218/1326] Minor --- src/hb-directwrite.cc | 4 ++-- src/hb-shape.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index b5c1113b1..11b935310 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -671,7 +671,7 @@ retry_getglyphs: DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties = (DWRITE_SHAPING_GLYPH_PROPERTIES*) malloc (maxGlyphCount * sizeof (DWRITE_SHAPING_GLYPH_PROPERTIES)); - hr = analyzer->GetGlyphs (textString, textLength, fontFace, FALSE, + hr = analyzer->GetGlyphs (textString, textLength, fontFace, false, isRightToLeft, &runHead->mScript, localeName, NULL, &dwFeatures, featureRangeLengths, 1, maxGlyphCount, clusterMap, textProperties, glyphIndices, glyphProperties, &glyphCount); @@ -719,7 +719,7 @@ retry_getglyphs: hr = analyzer->GetGlyphPlacements (textString, clusterMap, textProperties, textLength, glyphIndices, glyphProperties, glyphCount, fontFace, fontEmSize, - FALSE, isRightToLeft, &runHead->mScript, localeName, + false, isRightToLeft, &runHead->mScript, localeName, &dwFeatures, featureRangeLengths, 1, glyphAdvances, glyphOffsets); diff --git a/src/hb-shape.cc b/src/hb-shape.cc index f57cad903..f080a15e3 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -114,7 +114,7 @@ retry: * shapers will be used in the given order, otherwise the default shapers list * will be used. * - * Return value: %FALSE if all shapers failed, %TRUE otherwise + * Return value: false if all shapers failed, true otherwise * * Since: 0.9.2 **/ From d2f249e745a9179943ee39c719b73e1057acbc13 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 17:42:33 -0800 Subject: [PATCH 0219/1326] Stub out doc comments for new symbols --- docs/harfbuzz-docs.xml | 2 +- docs/harfbuzz-sections.txt | 35 +++++++++++++++++++++++++++++++++-- src/hb-common.cc | 10 ++++++++++ src/hb-common.h | 5 +++++ src/hb-directwrite.cc | 2 +- src/hb-directwrite.h | 2 +- src/hb-font.cc | 20 ++++++++++++++++++++ src/hb-ot-var.cc | 24 ++++++++++++++++++++++-- src/hb-ot-var.h | 12 +++++------- src/hb-set.cc | 2 +- 10 files changed, 99 insertions(+), 15 deletions(-) diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml index 7a42d2378..00113e985 100644 --- a/docs/harfbuzz-docs.xml +++ b/docs/harfbuzz-docs.xml @@ -180,7 +180,7 @@ Index of new symbols in 1.2.3 - + Index of new symbols in 1.3.3 diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 270c87c44..b4ae15dd5 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -245,6 +245,7 @@ hb_font_get_scale hb_font_get_user_data hb_font_get_variation_glyph hb_font_get_variation_glyph_func_t +hb_font_get_var_coords_normalized hb_font_glyph_from_string hb_font_glyph_to_string hb_font_is_immutable @@ -252,9 +253,16 @@ hb_font_make_immutable hb_font_reference hb_font_set_funcs hb_font_set_funcs_data +hb_font_set_parent hb_font_set_ppem hb_font_set_scale hb_font_set_user_data +hb_variation_t +hb_variation_from_string +hb_variation_to_string +hb_font_set_variations +hb_font_set_var_coords_design +hb_font_set_var_coords_normalized hb_font_subtract_glyph_origin_for_direction hb_font_t hb_reference_table_func_t @@ -266,7 +274,6 @@ hb_font_get_font_h_extents_func_t hb_font_get_font_v_extents_func_t hb_font_get_h_extents hb_font_get_v_extents -hb_font_set_parent
    @@ -304,6 +311,9 @@ HB_GOBJECT_TYPE_FONT HB_GOBJECT_TYPE_FONT_FUNCS HB_GOBJECT_TYPE_MEMORY_MODE HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS +HB_GOBJECT_TYPE_OT_MATH_CONSTANT +HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART_FLAGS +HB_GOBJECT_TYPE_OT_MATH_KERN HB_GOBJECT_TYPE_SCRIPT HB_GOBJECT_TYPE_SHAPE_PLAN HB_GOBJECT_TYPE_UNICODE_COMBINING_CLASS @@ -328,6 +338,9 @@ hb_gobject_font_funcs_get_type hb_gobject_font_get_type hb_gobject_memory_mode_get_type hb_gobject_ot_layout_glyph_class_get_type +hb_gobject_ot_math_constant_get_type +hb_gobject_ot_math_glyph_part_flags_get_type +hb_gobject_ot_math_kern_get_type hb_gobject_script_get_type hb_gobject_shape_plan_get_type hb_gobject_unicode_combining_class_get_type @@ -384,12 +397,14 @@ hb_ot_shape_glyphs_closure HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX HB_OT_LAYOUT_NO_FEATURE_INDEX HB_OT_LAYOUT_NO_SCRIPT_INDEX +HB_OT_LAYOUT_NO_VARIATIONS_INDEX HB_OT_TAG_GDEF HB_OT_TAG_GPOS HB_OT_TAG_GSUB HB_OT_TAG_JSTF hb_ot_layout_collect_lookups hb_ot_layout_feature_get_lookups +hb_ot_layout_feature_with_variations_get_lookups hb_ot_layout_get_attach_points hb_ot_layout_get_glyph_class hb_ot_layout_get_glyphs_in_class @@ -410,6 +425,7 @@ hb_ot_layout_lookup_would_substitute hb_ot_layout_script_find_language hb_ot_layout_script_get_language_tags hb_ot_layout_table_choose_script +hb_ot_layout_table_find_feature_variations hb_ot_layout_table_find_script hb_ot_layout_table_get_feature_tags hb_ot_layout_table_get_script_tags @@ -422,6 +438,19 @@ Xhb_ot_layout_lookup_position Xhb_ot_layout_lookup_substitute
    +
    +hb-ot-var +HB_OT_TAG_avar +HB_OT_TAG_fvar +HB_OT_VAR_NO_AXIS_INDEX +hb_ot_var_axis_t +hb_ot_var_has_data +hb_ot_var_find_axis +hb_ot_var_get_axis_count +hb_ot_var_get_axes +hb_ot_var_normalize_axis_value +
    +
    hb-ot-math HB_OT_TAG_MATH @@ -486,8 +515,8 @@ hb_set_union
    hb-shape -hb_feature_from_string hb_feature_t +hb_feature_from_string hb_feature_to_string hb_shape hb_shape_full @@ -498,6 +527,8 @@ hb_shape_list_shapers hb-shape-plan hb_shape_plan_create hb_shape_plan_create_cached +hb_shape_plan_create2 +hb_shape_plan_create_cached2 hb_shape_plan_destroy hb_shape_plan_execute hb_shape_plan_get_empty diff --git a/src/hb-common.cc b/src/hb-common.cc index a804f822b..64e77d434 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -898,6 +898,11 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation *pp == end; } +/** + * hb_variation_from_string: + * + * Since: 1.4.2 + */ hb_bool_t hb_variation_from_string (const char *str, int len, hb_variation_t *variation) @@ -919,6 +924,11 @@ hb_variation_from_string (const char *str, int len, return false; } +/** + * hb_variation_to_string: + * + * Since: 1.4.2 + */ void hb_variation_to_string (hb_variation_t *variation, char *buf, unsigned int size) diff --git a/src/hb-common.h b/src/hb-common.h index ed0b97dfd..634cb96a6 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -379,6 +379,11 @@ HB_EXTERN void hb_feature_to_string (hb_feature_t *feature, char *buf, unsigned int size); +/** + * hb_variation_t: + * + * Since: 1.4.2 + */ typedef struct hb_variation_t { hb_tag_t tag; float value; diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 11b935310..d63bc0473 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -915,7 +915,7 @@ _hb_directwrite_shape(hb_shape_plan_t *shape_plan, */ hb_bool_t -hb_shape_dwrite_experimental_width(hb_font_t *font, +hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features, diff --git a/src/hb-directwrite.h b/src/hb-directwrite.h index 0eb116f4c..e743af214 100644 --- a/src/hb-directwrite.h +++ b/src/hb-directwrite.h @@ -30,7 +30,7 @@ HB_BEGIN_DECLS HB_EXTERN hb_bool_t -hb_shape_dwrite_experimental_width(hb_font_t *font, hb_buffer_t *buffer, +hb_directwrite_shape_experimental_width(hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features, float width); HB_END_DECLS diff --git a/src/hb-font.cc b/src/hb-font.cc index 607bd4893..3140ee47c 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1551,6 +1551,11 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, font->num_coords = coords_length; } +/** + * hb_font_set_variations: + * + * Since: 1.4.2 + */ void hb_font_set_variations (hb_font_t *font, const hb_variation_t *variations, @@ -1584,6 +1589,11 @@ hb_font_set_variations (hb_font_t *font, _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } +/** + * hb_font_set_var_coords_design: + * + * Since: 1.4.2 + */ void hb_font_set_var_coords_design (hb_font_t *font, const float *coords, @@ -1603,6 +1613,11 @@ hb_font_set_var_coords_design (hb_font_t *font, _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } +/** + * hb_font_set_var_coords_normalized: + * + * Since: 1.4.2 + */ void hb_font_set_var_coords_normalized (hb_font_t *font, const int *coords, /* 2.14 normalized */ @@ -1621,6 +1636,11 @@ hb_font_set_var_coords_normalized (hb_font_t *font, _hb_font_adopt_var_coords_normalized (font, copy, coords_length); } +/** + * hb_font_set_var_coords_normalized: + * + * Since: 1.4.2 + */ int * hb_font_get_var_coords_normalized (hb_font_t *font, unsigned int *length) diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index d1e97257c..508042477 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -63,6 +63,11 @@ hb_ot_var_has_data (hb_face_t *face) return &_get_fvar (face) != &OT::Null(OT::fvar); } +/** + * hb_ot_var_get_axis_count: + * + * Since: 1.4.2 + **/ unsigned int hb_ot_var_get_axis_count (hb_face_t *face) { @@ -70,6 +75,11 @@ hb_ot_var_get_axis_count (hb_face_t *face) return fvar.get_axis_count (); } +/** + * hb_ot_var_get_axes: + * + * Since: 1.4.2 + **/ unsigned int hb_ot_var_get_axes (hb_face_t *face, unsigned int start_offset, @@ -80,7 +90,12 @@ hb_ot_var_get_axes (hb_face_t *face, return fvar.get_axis_infos (start_offset, axes_count, axes_array); } -HB_EXTERN hb_bool_t +/** + * hb_ot_var_find_axis: + * + * Since: 1.4.2 + **/ +hb_bool_t hb_ot_var_find_axis (hb_face_t *face, hb_tag_t axis_tag, unsigned int *axis_index, @@ -90,7 +105,12 @@ hb_ot_var_find_axis (hb_face_t *face, return fvar.find_axis (axis_tag, axis_index, axis_info); } -HB_EXTERN int +/** + * hb_ot_var_normalize_axis_value: + * + * Since: 1.4.2 + **/ +int hb_ot_var_normalize_axis_value (hb_face_t *face, unsigned int axis_index, float v) diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index 4023b29f4..652a78d07 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -60,6 +60,11 @@ typedef struct hb_ot_var_axis_t { HB_EXTERN hb_bool_t hb_ot_var_has_data (hb_face_t *face); +/** + * HB_OT_VAR_NO_AXIS_INDEX: + * + * Since: 1.4.2 + */ #define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu HB_EXTERN unsigned int @@ -83,13 +88,6 @@ hb_ot_var_normalize_axis_value (hb_face_t *face, unsigned int axis_index, float v); -#if 0 - -HB_EXTERN unsigned int -Xhb_ot_var_get_named_instances (hb_face_t *face, ... ); - -#endif - HB_END_DECLS diff --git a/src/hb-set.cc b/src/hb-set.cc index cb7fcdbf6..f3fe1ba43 100644 --- a/src/hb-set.cc +++ b/src/hb-set.cc @@ -105,7 +105,7 @@ hb_set_destroy (hb_set_t *set) * @set: a set. * @key: * @data: - * @destroy (closure data): + * @destroy: * @replace: * * Return value: From 7647a05a0b37c53465560952b412db4e590f2716 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 17:47:49 -0800 Subject: [PATCH 0220/1326] Minor --- src/hb-font.cc | 5 ++++- src/hb-font.h | 2 +- src/hb-ft.cc | 2 +- util/helper-cairo.cc | 14 +++++++++----- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index 3140ee47c..a3f250d50 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1639,9 +1639,12 @@ hb_font_set_var_coords_normalized (hb_font_t *font, /** * hb_font_set_var_coords_normalized: * + * Return value is valid as long as variation coordinates of the font + * are not modified. + * * Since: 1.4.2 */ -int * +const int * hb_font_get_var_coords_normalized (hb_font_t *font, unsigned int *length) { diff --git a/src/hb-font.h b/src/hb-font.h index fce4206df..e2e59796f 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -618,7 +618,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, const int *coords, /* 2.14 normalized */ unsigned int coords_length); -HB_EXTERN int * +HB_EXTERN const int * hb_font_get_var_coords_normalized (hb_font_t *font, unsigned int *length); diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 496fff230..48d6a0efb 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -742,7 +742,7 @@ hb_ft_font_set_funcs (hb_font_t *font) } unsigned int num_coords; - int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); if (num_coords) { FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed)); diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc index df5173b59..2e2952b28 100644 --- a/util/helper-cairo.cc +++ b/util/helper-cairo.cc @@ -104,13 +104,17 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts) else { unsigned int num_coords; - int *coords = hb_font_get_var_coords_normalized (font, &num_coords); + const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); if (num_coords) { - FT_Fixed ft_coords[num_coords]; - for (unsigned int i = 0; i < num_coords; i++) - ft_coords[i] = coords[i] << 2; - FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + FT_Fixed *ft_coords = (FT_Fixed *) calloc (num_coords, sizeof (FT_Fixed)); + if (ft_coords) + { + for (unsigned int i = 0; i < num_coords; i++) + ft_coords[i] = coords[i] << 2; + FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords); + free (ft_coords); + } } cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); From 8a577aaa0dd760409bcad1ae3d4f5fb561a62a4b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 18:22:40 -0800 Subject: [PATCH 0221/1326] [var] Stub implementation of avar table --- src/hb-ot-var-avar-table.hh | 99 +++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/hb-ot-var-avar-table.hh diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh new file mode 100644 index 000000000..a041934bf --- /dev/null +++ b/src/hb-ot-var-avar-table.hh @@ -0,0 +1,99 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_AVAR_TABLE_HH +#define HB_OT_VAR_AVAR_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-var.h" + +namespace OT { + + +struct AxisValueMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + F2DOT14 fromCoord; /* A normalized coordinate value obtained using + * default normalization. */ + F2DOT14 toCoord; /* The modified, normalized coordinate value. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +typedef ArrayOf SegmentMaps; + +/* + * avar — Axis Variations Table + */ + +struct avar +{ + static const hb_tag_t tableTag = HB_OT_TAG_avar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!(version.sanitize (c) && + version.major == 1 && + c->check_struct (this)))) + return_trace (false); + + const SegmentMaps *map = &axisSegmentMapsZ; + unsigned int count = axisCount; + for (unsigned int i = 0; i < count; i++) + { + if (unlikely (!map->sanitize (c))) + return_trace (false); + map = &StructAfter (*map); + } + + return_trace (true); + } + + protected: + FixedVersion<>version; /* Version of the avar table + * initially set to 0x00010000u */ + USHORT reserved; /* This field is permanently reserved. Set to 0. */ + USHORT axisCount; /* The number of variation axes in the font. This + * must be the same number as axisCount in the + * 'fvar' table. */ + SegmentMaps axisSegmentMapsZ; + + public: + DEFINE_SIZE_MIN (8); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_AVAR_TABLE_HH */ From 5ec96d30cad1592b5e468bd8ad1832dbaf0ad32b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 18:52:00 -0800 Subject: [PATCH 0222/1326] [var] Adjust API in prep for 'avar' implementation The 'avar' table does not allow random access to axis maps, so change API to avoid quadratic-time implementation. Removed -hb_ot_var_normalize_axis_value(), added +hb_ot_var_normalize_variations() and +hb_ot_var_normalize_coords() instead. --- docs/harfbuzz-sections.txt | 3 ++- src/Makefile.sources | 1 + src/hb-font.cc | 20 +++++------------ src/hb-ot-var.cc | 45 +++++++++++++++++++++++++++++++++----- src/hb-ot-var.h | 16 ++++++++++---- 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index b4ae15dd5..fcf4e527e 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -448,7 +448,8 @@ hb_ot_var_has_data hb_ot_var_find_axis hb_ot_var_get_axis_count hb_ot_var_get_axes -hb_ot_var_normalize_axis_value +hb_ot_var_normalize_variations +hb_ot_var_normalize_coords
    diff --git a/src/Makefile.sources b/src/Makefile.sources index 279bc46eb..c74147cb5 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -109,6 +109,7 @@ HB_OT_sources = \ hb-ot-shape-fallback.cc \ hb-ot-shape-private.hh \ hb-ot-var.cc \ + hb-ot-var-avar-table.hh \ hb-ot-var-fvar-table.hh \ $(NULL) diff --git a/src/hb-font.cc b/src/hb-font.cc index a3f250d50..ea4550126 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1570,22 +1570,15 @@ hb_font_set_variations (hb_font_t *font, return; } - hb_face_t *face = font->face; - - unsigned int coords_length = hb_ot_var_get_axis_count (face); + unsigned int coords_length = hb_ot_var_get_axis_count (font->face); int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : NULL; if (unlikely (coords_length && !normalized)) return; - /* normalized is filled with zero already. */ - for (unsigned int i = 0; i < variations_length; i++) - { - unsigned int axis_index; - if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL)) - normalized[axis_index] = hb_ot_var_normalize_axis_value (face, axis_index, variations[i].value); - } - + hb_ot_var_normalize_variations (font->face, + variations, variations_length, + normalized, coords_length); _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } @@ -1606,10 +1599,7 @@ hb_font_set_var_coords_design (hb_font_t *font, if (unlikely (coords_length && !normalized)) return; - hb_face_t *face = font->face; - for (unsigned int i = 0; i < coords_length; i++) - normalized[i] = hb_ot_var_normalize_axis_value (face, i, coords[i]); - + hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized); _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); } diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index 508042477..76016e634 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -27,6 +27,7 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-private.hh" +#include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" #include "hb-ot-var.h" @@ -105,16 +106,48 @@ hb_ot_var_find_axis (hb_face_t *face, return fvar.find_axis (axis_tag, axis_index, axis_info); } + /** - * hb_ot_var_normalize_axis_value: + * hb_ot_var_normalize_variations: * * Since: 1.4.2 **/ -int -hb_ot_var_normalize_axis_value (hb_face_t *face, - unsigned int axis_index, - float v) +void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length) +{ + for (unsigned int i = 0; i < coords_length; i++) + coords[i] = 0; + + const OT::fvar &fvar = _get_fvar (face); + for (unsigned int i = 0; i < variations_length; i++) + { + unsigned int axis_index; + if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, NULL) && + axis_index < coords_length) + coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value); + } + + /* TODO avar */ +} + +/** + * hb_ot_var_normalize_coords: + * + * Since: 1.4.2 + **/ +void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */) { const OT::fvar &fvar = _get_fvar (face); - return fvar.normalize_axis_value (axis_index, v); + for (unsigned int i = 0; i < coords_length; i++) + normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]); + + /* TODO avar */ } diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index 652a78d07..bce7c7a0a 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -83,10 +83,18 @@ hb_ot_var_find_axis (hb_face_t *face, hb_ot_var_axis_t *axis_info); -HB_EXTERN int -hb_ot_var_normalize_axis_value (hb_face_t *face, - unsigned int axis_index, - float v); +HB_EXTERN void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length); + +HB_EXTERN void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */); HB_END_DECLS From a42909057207cbed1ef95716170434c05beb0002 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 19:01:07 -0800 Subject: [PATCH 0223/1326] [var] Flesh out --variations documentation --- util/options.cc | 53 +++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/util/options.cc b/util/options.cc index 8c79c4ad6..0f2e207d0 100644 --- a/util/options.cc +++ b/util/options.cc @@ -311,7 +311,7 @@ view_options_t::add_options (option_parser_t *parser) parser->add_group (entries, "view", "View options:", - "Options controlling output rendering", + "Options for output rendering", this); } @@ -340,7 +340,7 @@ shape_options_t::add_options (option_parser_t *parser) parser->add_group (entries, "shape", "Shape options:", - "Options controlling the shaping process", + "Options for the shaping process", this); const gchar *features_help = "Comma-separated list of font features\n" @@ -387,7 +387,7 @@ shape_options_t::add_options (option_parser_t *parser) parser->add_group (entries2, "features", "Features options:", - "Options controlling font features used", + "Options for font features used", this); } @@ -454,45 +454,20 @@ font_options_t::add_options (option_parser_t *parser) parser->add_group (entries, "font", "Font options:", - "Options controlling the font", + "Options for the font", this); const gchar *variations_help = "Comma-separated list of font variations\n" "\n" - " XXXXXXXXXXXXXXX\n" - " Features can be enabled or disabled, either globally or limited to\n" - " specific character ranges. The format for specifying feature settings\n" - " follows. All valid CSS font-feature-settings values other than 'normal'\n" + " Variations are set globally. The format for specifying variation settings\n" + " follows. All valid CSS font-variation-settings values other than 'normal'\n" " and 'inherited' are also accepted, though, not documented below.\n" "\n" - " The range indices refer to the positions between Unicode characters,\n" - " unless the --utf8-clusters is provided, in which case range indices\n" - " refer to UTF-8 byte indices. The position before the first character\n" - " is always 0.\n" + " The format is a tag, optionally followed by an equals sign, followed by a\n" + " number. For example:\n" "\n" - " The format is Python-esque. Here is how it all works:\n" - "\n" - " Syntax: Value: Start: End:\n" - "\n" - " Setting value:\n" - " \"kern\" 1 0 ∞ # Turn feature on\n" - " \"+kern\" 1 0 ∞ # Turn feature on\n" - " \"-kern\" 0 0 ∞ # Turn feature off\n" - " \"kern=0\" 0 0 ∞ # Turn feature off\n" - " \"kern=1\" 1 0 ∞ # Turn feature on\n" - " \"aalt=2\" 2 0 ∞ # Choose 2nd alternate\n" - "\n" - " Setting index:\n" - " \"kern[]\" 1 0 ∞ # Turn feature on\n" - " \"kern[:]\" 1 0 ∞ # Turn feature on\n" - " \"kern[5:]\" 1 5 ∞ # Turn feature on, partial\n" - " \"kern[:5]\" 1 0 5 # Turn feature on, partial\n" - " \"kern[3:5]\" 1 3 5 # Turn feature on, range\n" - " \"kern[3]\" 1 3 3+1 # Turn feature on, single char\n" - "\n" - " Mixing it all:\n" - "\n" - " \"aalt[3:5]=2\" 2 3 5 # Turn 2nd alternate on for range"; + " \"wght=500\"\n" + " \"slnt=-7.5\"\n"; GOptionEntry entries2[] = { @@ -502,7 +477,7 @@ font_options_t::add_options (option_parser_t *parser) parser->add_group (entries2, "variations", "Varitions options:", - "Options controlling font variations used", + "Options for font variations used", this); } @@ -520,7 +495,7 @@ text_options_t::add_options (option_parser_t *parser) parser->add_group (entries, "text", "Text options:", - "Options controlling the input text", + "Options for the input text", this); } @@ -548,7 +523,7 @@ output_options_t::add_options (option_parser_t *parser) parser->add_group (entries, "output", "Output destination & format options:", - "Options controlling the destination and form of the output", + "Options for the destination & form of the output", this); } @@ -810,7 +785,7 @@ format_options_t::add_options (option_parser_t *parser) " text: [=@,+,|...]\n" " json: [{\"g\": , \"ax\": , \"ay\": , \"dx\": , \"dy\": , \"cl\": }, ...]\n" "\nOutput syntax options:", - "Options controlling the syntax of the output", + "Options for the syntax of the output", this); } From a484e237b11650d00092329855d33dd2f67980e4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 19:41:33 -0800 Subject: [PATCH 0224/1326] [var] Implement 'avar' table mapping Untested! --- src/hb-ot-math.cc | 2 -- src/hb-ot-var-avar-table.hh | 46 ++++++++++++++++++++++++++++++++++++- src/hb-ot-var.cc | 23 ++++++++++++------- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index eb08badbd..2d7e6792a 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -34,9 +34,7 @@ static inline const OT::MATH& _get_math (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->math.get ()); } diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh index a041934bf..743d5870e 100644 --- a/src/hb-ot-var-avar-table.hh +++ b/src/hb-ot-var-avar-table.hh @@ -50,7 +50,39 @@ struct AxisValueMap DEFINE_SIZE_STATIC (4); }; -typedef ArrayOf SegmentMaps; +struct SegmentMaps : ArrayOf +{ + inline int map (int value) const + { + /* The following special-cases are not part of OpenType, which requires + * that at least -1, 0, and +1 must be mapped. But we include these as + * part of a better error recovery scheme. */ + + if (!len) + return value; + + if (value <= array[0].fromCoord) + return value - array[0].fromCoord + array[0].toCoord; + + unsigned int i; + unsigned int count = len; + for (i = 1; i < count && value > array[i].fromCoord; i++) + ; + + if (value >= array[i].fromCoord) + return value - array[i].fromCoord + array[i].toCoord; + + if (unlikely (array[i-1].fromCoord == array[i].fromCoord)) + return array[i-1].toCoord; + + int denom = array[i].fromCoord - array[i-1].fromCoord; + return array[i-1].toCoord + + (array[i].toCoord - array[i-1].toCoord) * + (value - array[i-1].fromCoord + denom/2) / denom; + } + + DEFINE_SIZE_ARRAY (2, array); +}; /* * avar — Axis Variations Table @@ -80,6 +112,18 @@ struct avar return_trace (true); } + inline void map_coords (int *coords, unsigned int coords_length) const + { + unsigned int count = MIN (coords_length, axisCount); + + const SegmentMaps *map = &axisSegmentMapsZ; + for (unsigned int i = 0; i < count; i++) + { + coords[i] = map->map (coords[i]); + map = &StructAfter (*map); + } + } + protected: FixedVersion<>version; /* Version of the avar table * initially set to 0x00010000u */ diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index 76016e634..d4d16dfff 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -33,19 +33,24 @@ HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) +/* + * fvar/avar + */ + static inline const OT::fvar& _get_fvar (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar); - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - return *(layout->fvar.get ()); } - -/* - * fvar/avar - */ +static inline const OT::avar& +_get_avar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->avar.get ()); +} /** * hb_ot_var_has_data: @@ -131,7 +136,8 @@ hb_ot_var_normalize_variations (hb_face_t *face, coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value); } - /* TODO avar */ + const OT::avar &avar = _get_avar (face); + avar.map_coords (coords, coords_length); } /** @@ -149,5 +155,6 @@ hb_ot_var_normalize_coords (hb_face_t *face, for (unsigned int i = 0; i < coords_length; i++) normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]); - /* TODO avar */ + const OT::avar &avar = _get_avar (face); + avar.map_coords (normalized_coords, coords_length); } From 7a860f656e4aec45c45e0f5fb28c49a91dc5eef2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 19:52:09 -0800 Subject: [PATCH 0225/1326] [var] Add macros for standard axes --- docs/harfbuzz-sections.txt | 7 +++++++ src/hb-ot-var.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index fcf4e527e..3011ee996 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -442,6 +442,11 @@ Xhb_ot_layout_lookup_substitute hb-ot-var HB_OT_TAG_avar HB_OT_TAG_fvar +HB_OT_TAG_VAR_AXIS_ITALIC +HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE +HB_OT_TAG_VAR_AXIS_SLANT +HB_OT_TAG_VAR_AXIS_WEIGHT +HB_OT_TAG_VAR_AXIS_WIDTH HB_OT_VAR_NO_AXIS_INDEX hb_ot_var_axis_t hb_ot_var_has_data @@ -584,6 +589,8 @@ hb_unicode_script_func_t hb-uniscribe hb_uniscribe_font_get_hfont hb_uniscribe_font_get_logfontw + +hb_directwrite_shape_experimental_width
    diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index bce7c7a0a..ea69aa5fc 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -39,6 +39,12 @@ HB_BEGIN_DECLS #define HB_OT_TAG_fvar HB_TAG('f','v','a','r') #define HB_OT_TAG_avar HB_TAG('a','v','a','r') +#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l') +#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z') +#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t') +#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h') +#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t') + /* * fvar / avar From a11d9a0466e480efebd69a34827675387cd2ca34 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 20:09:47 -0800 Subject: [PATCH 0226/1326] Minor --- src/hb-ot-font.cc | 6 +++--- src/hb-ot-hmtx-table.hh | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index c4ec612c8..f84dbc285 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -50,7 +50,7 @@ struct hb_ot_face_metrics_accelerator_t unsigned short line_gap; bool has_font_extents; - const OT::_mtx *table; + const OT::hmtxvmtx *table; hb_blob_t *blob; inline void init (hb_face_t *face, @@ -91,7 +91,7 @@ struct hb_ot_face_metrics_accelerator_t this->has_font_extents = got_font_extents; - this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); + this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag)); /* Cap num_metrics() and num_advances() based on table length. */ unsigned int len = hb_blob_get_length (this->blob); @@ -107,7 +107,7 @@ struct hb_ot_face_metrics_accelerator_t hb_blob_destroy (this->blob); this->blob = hb_blob_get_empty (); } - this->table = OT::Sanitizer::lock_instance (this->blob); + this->table = OT::Sanitizer::lock_instance (this->blob); } inline void fini (void) diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index a9606b3d2..30aa62534 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -50,10 +50,8 @@ struct LongMetric DEFINE_SIZE_STATIC (4); }; -struct _mtx +struct hmtxvmtx { - static const hb_tag_t tableTag = HB_TAG('_','m','t','x'); - static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; @@ -91,10 +89,10 @@ struct _mtx DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); }; -struct hmtx : _mtx { +struct hmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_hmtx; }; -struct vmtx : _mtx { +struct vmtx : hmtxvmtx { static const hb_tag_t tableTag = HB_OT_TAG_vmtx; }; From d6bdbbca307d1a4aed60a78133eea40a1a9d5bf3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 20:16:51 -0800 Subject: [PATCH 0227/1326] [var] Remove HB_OT_TAG_fvar/avar We're not going to define public macros for tags for tables. There's little use to those and they are implementation detail. --- docs/harfbuzz-sections.txt | 2 -- src/hb-ot-var-avar-table.hh | 2 ++ src/hb-ot-var-fvar-table.hh | 2 ++ src/hb-ot-var.h | 3 --- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 3011ee996..a91eb4c2c 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -440,8 +440,6 @@ Xhb_ot_layout_lookup_substitute
    hb-ot-var -HB_OT_TAG_avar -HB_OT_TAG_fvar HB_OT_TAG_VAR_AXIS_ITALIC HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_OT_TAG_VAR_AXIS_SLANT diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh index 743d5870e..7c8449a84 100644 --- a/src/hb-ot-var-avar-table.hh +++ b/src/hb-ot-var-avar-table.hh @@ -88,6 +88,8 @@ struct SegmentMaps : ArrayOf * avar — Axis Variations Table */ +#define HB_OT_TAG_avar HB_TAG('a','v','a','r') + struct avar { static const hb_tag_t tableTag = HB_OT_TAG_avar; diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index cb88de883..0c48769df 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -81,6 +81,8 @@ struct AxisRecord * fvar — Font Variations Table */ +#define HB_OT_TAG_fvar HB_TAG('f','v','a','r') + struct fvar { static const hb_tag_t tableTag = HB_OT_TAG_fvar; diff --git a/src/hb-ot-var.h b/src/hb-ot-var.h index ea69aa5fc..a2c0c5f2b 100644 --- a/src/hb-ot-var.h +++ b/src/hb-ot-var.h @@ -36,9 +36,6 @@ HB_BEGIN_DECLS -#define HB_OT_TAG_fvar HB_TAG('f','v','a','r') -#define HB_OT_TAG_avar HB_TAG('a','v','a','r') - #define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l') #define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z') #define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t') From 5e156fa5ed33cd1a8ff388833563f15930bb12f9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 20:28:56 -0800 Subject: [PATCH 0228/1326] Add LOffsetTo<> --- src/hb-open-file-private.hh | 2 +- src/hb-open-type-private.hh | 1 + src/hb-ot-cbdt-table.hh | 4 ++-- src/hb-ot-cmap-table.hh | 6 +++--- src/hb-ot-layout-common-private.hh | 10 +++++----- src/hb-ot-layout-gdef-table.hh | 4 ++-- src/hb-ot-layout-gsubgpos-private.hh | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh index 5357ddcf5..f208419aa 100644 --- a/src/hb-open-file-private.hh +++ b/src/hb-open-file-private.hh @@ -142,7 +142,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - ArrayOf, ULONG> + ArrayOf, ULONG> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 8845e3eee..8bd361868 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -830,6 +830,7 @@ struct OffsetTo : Offset } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; +template struct LOffsetTo : OffsetTo {}; template static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } template diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 52897abd3..93cf0e853 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -216,7 +216,7 @@ struct IndexSubtableRecord USHORT firstGlyphIndex; USHORT lastGlyphIndex; - OffsetTo offsetToSubtable; + LOffsetTo offsetToSubtable; DEFINE_SIZE_STATIC(8); }; @@ -275,7 +275,7 @@ struct BitmapSizeTable } protected: - OffsetTo indexSubtableArrayOffset; + LOffsetTo indexSubtableArrayOffset; ULONG indexTablesSize; ULONG numberOfIndexSubtables; ULONG colorRef; diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index d7a94a1ef..3a53a1cb5 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -380,9 +380,9 @@ struct VariationSelectorRecord } UINT24 varSelector; /* Variation selector. */ - OffsetTo + LOffsetTo defaultUVS; /* Offset to Default UVS Table. May be 0. */ - OffsetTo + LOffsetTo nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -486,7 +486,7 @@ struct EncodingRecord USHORT platformID; /* Platform ID. */ USHORT encodingID; /* Platform-specific encoding ID. */ - OffsetTo + LOffsetTo subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 62ca7a348..2f83497b4 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1334,7 +1334,7 @@ struct VariationStore protected: USHORT format; - OffsetTo regions; + LOffsetTo regions; OffsetArrayOf dataSets; public: DEFINE_SIZE_ARRAY (8, dataSets); @@ -1433,8 +1433,8 @@ struct FeatureTableSubstitutionRecord } protected: - USHORT featureIndex; - OffsetTo feature; + USHORT featureIndex; + LOffsetTo feature; public: DEFINE_SIZE_STATIC (6); }; @@ -1481,9 +1481,9 @@ struct FeatureVariationRecord } protected: - OffsetTo + LOffsetTo conditions; - OffsetTo + LOffsetTo substitutions; public: DEFINE_SIZE_STATIC (8); diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index b70cbb7a3..552df0fd8 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -295,7 +295,7 @@ struct MarkGlyphSetsFormat1 protected: USHORT format; /* Format identifier--format = 1 */ - ArrayOf > + ArrayOf > coverage; /* Array of long offsets to mark set * coverage tables */ public: @@ -443,7 +443,7 @@ struct GDEF * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 0x00010002. */ - OffsetTo + LOffsetTo varStore; /* Offset to the table of Item Variation * Store--from beginning of GDEF * header (may be NULL). Introduced diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index fd75c5425..b7a0122a3 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -2313,7 +2313,7 @@ struct GSUBGPOS featureList; /* FeatureList table */ OffsetTo lookupList; /* LookupList table */ - OffsetTo + LOffsetTo featureVars; /* Offset to Feature Variations table--from beginning of table * (may be NULL). Introduced From b732c53eb5bd0c2cc86f35a9d9623c92579a0b8c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 22 Jan 2017 20:31:53 -0800 Subject: [PATCH 0229/1326] Add LArrayOf<> --- src/hb-open-type-private.hh | 1 + src/hb-ot-cbdt-table.hh | 4 ++-- src/hb-ot-layout-common-private.hh | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 8bd361868..d90d68c59 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -952,6 +952,7 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), array); }; +template struct LArrayOf : ArrayOf {}; /* Array of Offset's */ template diff --git a/src/hb-ot-cbdt-table.hh b/src/hb-ot-cbdt-table.hh index 93cf0e853..0a7fbf5b7 100644 --- a/src/hb-ot-cbdt-table.hh +++ b/src/hb-ot-cbdt-table.hh @@ -348,8 +348,8 @@ struct CBLC } protected: - FixedVersion<>version; - ArrayOf sizeTables; + FixedVersion<> version; + LArrayOf sizeTables; public: DEFINE_SIZE_ARRAY(8, sizeTables); diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 2f83497b4..92b5c17ee 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1527,7 +1527,7 @@ struct FeatureVariations protected: FixedVersion<> version; /* Version--0x00010000u */ - ArrayOf + LArrayOf varRecords; public: DEFINE_SIZE_ARRAY (8, varRecords); From 7b399f73efa76cd97131fd123a9a1566f8639cfd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 11:41:43 -0800 Subject: [PATCH 0230/1326] [var] Start adding HVAR/VVAR --- src/Makefile.sources | 1 + src/hb-ot-font.cc | 1 + src/hb-ot-var-avar-table.hh | 1 - src/hb-ot-var-fvar-table.hh | 1 - src/hb-ot-var-hvar-table.hh | 115 ++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 src/hb-ot-var-hvar-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index c74147cb5..8d7f1a05d 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -111,6 +111,7 @@ HB_OT_sources = \ hb-ot-var.cc \ hb-ot-var-avar-table.hh \ hb-ot-var-fvar-table.hh \ + hb-ot-var-hvar-table.hh \ $(NULL) HB_OT_headers = \ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index f84dbc285..c7286b7eb 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -37,6 +37,7 @@ #include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" #include "hb-ot-os2-table.hh" +#include "hb-ot-var-hvar-table.hh" //#include "hb-ot-post-table.hh" diff --git a/src/hb-ot-var-avar-table.hh b/src/hb-ot-var-avar-table.hh index 7c8449a84..ace0f5f28 100644 --- a/src/hb-ot-var-avar-table.hh +++ b/src/hb-ot-var-avar-table.hh @@ -28,7 +28,6 @@ #define HB_OT_VAR_AVAR_TABLE_HH #include "hb-open-type-private.hh" -#include "hb-ot-var.h" namespace OT { diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh index 0c48769df..9f6fb3250 100644 --- a/src/hb-ot-var-fvar-table.hh +++ b/src/hb-ot-var-fvar-table.hh @@ -28,7 +28,6 @@ #define HB_OT_VAR_FVAR_TABLE_HH #include "hb-open-type-private.hh" -#include "hb-ot-var.h" namespace OT { diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh new file mode 100644 index 000000000..0cb24d25a --- /dev/null +++ b/src/hb-ot-var-hvar-table.hh @@ -0,0 +1,115 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_HVAR_TABLE_HH +#define HB_OT_VAR_HVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct DeltaSetIndexMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (this, 1, 12)); + } + + USHORT x; + public: + DEFINE_SIZE_STATIC (2); +}; + + +/* + * HVAR -- The Horizontal Metrics Variations Table + * VVAR -- The Vertical Metrics Variations Table + */ + +#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R') +#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R') + +struct HVARVVAR +{ + static const hb_tag_t HVARTag = HB_OT_TAG_hmtx; + static const hb_tag_t VVARTag = HB_OT_TAG_vmtx; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varStore.sanitize (c, this) && + advMap.sanitize (c, this) && + lsbMap.sanitize (c, this) && + rsbMap.sanitize (c, this)); + } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + LOffsetTo + varStore; /* Offset to item variation store table. */ + LOffsetTo + advMap; /* Offset to advance var-idx mapping. */ + LOffsetTo + lsbMap; /* Offset to lsb/tsb var-idx mapping. */ + LOffsetTo + rsbMap; /* Offset to rsb/bsb var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + +struct HVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_HVAR; +}; +struct VVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_VVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (static_cast (this)->sanitize (c) && + vorgMap.sanitize (c, this)); + } + + protected: + LOffsetTo + vorgMap; /* Offset to vertical-origin var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (24); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_HVAR_TABLE_HH */ From a4fca9f0051dbc177390a4e555b2d0fe642f724e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 11:56:08 -0800 Subject: [PATCH 0231/1326] [var] Implement DeltaSetIndexMap and advance delta fetching Not hooked up to hb-ot-font yet. --- src/hb-ot-layout-common-private.hh | 8 +++++ src/hb-ot-var-hvar-table.hh | 56 ++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 92b5c17ee..180e5f086 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -1323,6 +1323,14 @@ struct VariationStore this+regions); } + inline float get_delta (unsigned int index, + int *coords, unsigned int coord_count) const + { + unsigned int outer = index >> 16; + unsigned int inner = index & 0xFFFF; + return get_delta (outer, inner, coords, coord_count); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index 0cb24d25a..cf22c9d9c 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -39,12 +39,52 @@ struct DeltaSetIndexMap { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (this, 1, 12)); + c->check_array (mapData, get_width (), mapCount)); } - USHORT x; + unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ + { + /* If count is zero, pass value unchanged. This takes + * care of direct mapping for advance map. */ + if (!mapCount) + return v; + + if (v >= mapCount) + v = mapCount - 1; + + unsigned int u = 0; + { /* Fetch it. */ + unsigned int w = get_width (); + const BYTE *p = mapData + w * v; + for (; w; w--) + u = (u << 8) + *p++; + } + + { /* Repack it. */ + unsigned int n = get_inner_bitcount (); + unsigned int outer = u >> n; + unsigned int inner = u & ((1 << n) - 1); + u = (outer<<16) | inner; + } + + return u; + } + + protected: + inline bool get_width (void) const + { return ((format >> 4) & 3) + 1; } + + inline bool get_inner_bitcount (void) const + { return (format & 0xF) + 1; } + + protected: + USHORT format; /* A packed field that describes the compressed + * representation of delta-set indices. */ + USHORT mapCount; /* The number of mapping entries. */ + BYTE mapData[VAR]; /* The delta-set index mapping data. */ + public: - DEFINE_SIZE_STATIC (2); + DEFINE_SIZE_ARRAY (4, mapData); }; @@ -72,6 +112,16 @@ struct HVARVVAR rsbMap.sanitize (c, this)); } + inline float get_advance_delta (hb_codepoint_t glyph, + int *coords, unsigned int coord_count) const + { + unsigned int varidx = (this+advMap).map (glyph); + return (this+varStore).get_delta (varidx, coords, coord_count); + } + + inline bool has_sidebearing_deltas (void) const + { return lsbMap && rsbMap; } + protected: FixedVersion<>version; /* Version of the metrics variation table * initially set to 0x00010000u */ From bd3b11d92663343350813ca29606b369f691af03 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 17:34:44 -0800 Subject: [PATCH 0232/1326] [var] Prepare for hooking up advance variations to hb-ot-font --- src/hb-ot-font.cc | 28 +++++++++++++++++----------- src/hb-ot-var-hvar-table.hh | 8 ++++---- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index c7286b7eb..c597f1456 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -54,9 +54,13 @@ struct hb_ot_face_metrics_accelerator_t const OT::hmtxvmtx *table; hb_blob_t *blob; + const OT::HVARVVAR *var; + hb_blob_t *var_blob; + inline void init (hb_face_t *face, hb_tag_t _hea_tag, hb_tag_t _mtx_tag, + hb_tag_t _var_tag, hb_tag_t os2_tag, unsigned int default_advance = 0) { @@ -109,14 +113,19 @@ struct hb_ot_face_metrics_accelerator_t this->blob = hb_blob_get_empty (); } this->table = OT::Sanitizer::lock_instance (this->blob); + + this->var_blob = OT::Sanitizer::sanitize (face->reference_table (_var_tag)); + this->var = OT::Sanitizer::lock_instance (this->var_blob); } inline void fini (void) { hb_blob_destroy (this->blob); + hb_blob_destroy (this->var_blob); } - inline unsigned int get_advance (hb_codepoint_t glyph) const + inline unsigned int get_advance (hb_codepoint_t glyph, + hb_font_t *font) const { if (unlikely (glyph >= this->num_metrics)) { @@ -129,10 +138,7 @@ struct hb_ot_face_metrics_accelerator_t return this->default_advance; } - if (glyph >= this->num_advances) - glyph = this->num_advances - 1; - - return this->table->longMetric[glyph].advance; + return this->table->longMetric[MIN (glyph, this->num_advances - 1)].advance; } }; @@ -441,8 +447,8 @@ _hb_ot_font_create (hb_face_t *face) return NULL; ot_font->cmap.init (face); - ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE, + ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_HVAR, HB_OT_TAG_os2); + ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_OT_TAG_VVAR, HB_TAG_NONE, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); ot_font->cbdt.init (face); @@ -488,23 +494,23 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, } static hb_position_t -hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_h_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font)); } static hb_position_t -hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_v_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); + return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font)); } static hb_bool_t diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index cf22c9d9c..9931a5e60 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -98,8 +98,8 @@ struct DeltaSetIndexMap struct HVARVVAR { - static const hb_tag_t HVARTag = HB_OT_TAG_hmtx; - static const hb_tag_t VVARTag = HB_OT_TAG_vmtx; + static const hb_tag_t HVARTag = HB_OT_TAG_HVAR; + static const hb_tag_t VVARTag = HB_OT_TAG_VVAR; inline bool sanitize (hb_sanitize_context_t *c) const { @@ -112,8 +112,8 @@ struct HVARVVAR rsbMap.sanitize (c, this)); } - inline float get_advance_delta (hb_codepoint_t glyph, - int *coords, unsigned int coord_count) const + inline float get_advance_var (hb_codepoint_t glyph, + int *coords, unsigned int coord_count) const { unsigned int varidx = (this+advMap).map (glyph); return (this+varStore).get_delta (varidx, coords, coord_count); From 607434037199ccca422287e4d097487f17f3cfb5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 17:55:16 -0800 Subject: [PATCH 0233/1326] [var] Fix bug in HVAR/VVAR impl --- src/hb-ot-var-hvar-table.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index 9931a5e60..3a2a82037 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -71,10 +71,10 @@ struct DeltaSetIndexMap } protected: - inline bool get_width (void) const + inline unsigned int get_width (void) const { return ((format >> 4) & 3) + 1; } - inline bool get_inner_bitcount (void) const + inline unsigned int get_inner_bitcount (void) const { return (format & 0xF) + 1; } protected: From 79e8e27ffd3da29ca27d3aebd2ef425bf1cb7f9d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 17:55:31 -0800 Subject: [PATCH 0234/1326] [var] Hook up advance variations to hb-ot-font Yay, works! --- src/hb-ot-font.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index c597f1456..009db20ae 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -138,7 +138,8 @@ struct hb_ot_face_metrics_accelerator_t return this->default_advance; } - return this->table->longMetric[MIN (glyph, this->num_advances - 1)].advance; + return this->table->longMetric[MIN (glyph, this->num_advances - 1)].advance + + this->var->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?! } }; @@ -524,6 +525,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, bool ret = ot_font->glyf->get_extents (glyph, extents); if (!ret) ret = ot_font->cbdt->get_extents (glyph, extents); + // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->width = font->em_scale_x (extents->width); @@ -541,6 +543,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); + // TODO Hook up variations. return ot_font->h_metrics.has_font_extents; } @@ -554,6 +557,7 @@ hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); + // TODO Hook up variations. return ot_font->v_metrics.has_font_extents; } From 6af6c1114a3495584ac4197c62592741c407b5a2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 18:35:00 -0800 Subject: [PATCH 0235/1326] 1.4.2 --- NEWS | 31 +++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8c3ef117d..43a3bacea 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +Overview of changes leading to 1.4.2 +Monday, January 23, 2017 +==================================== + +- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR. +- hb-shape and hb-view now accept --variations. +- New API: + +hb_variation_t +hb_variation_from_string() +hb_variation_to_string() + +hb_font_set_variations() +hb_font_set_var_coords_design() +hb_font_get_var_coords_normalized() + +hb-ot-var.h: +hb_ot_var_axis_t +hb_ot_var_has_data() +hb_ot_var_get_axis_count() +hb_ot_var_get_axes() +hb_ot_var_find_axis() +hb_ot_var_normalize_variations() +hb_ot_var_normalize_coords() + +- MVAR to be implemented later. Access to named instances to be + implemented later as well. + +- Misc fixes. + + Overview of changes leading to 1.4.1 Thursday, January 5, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 32dcf18ed..31fa97d3b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.1], + [1.4.2], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 67a191164dec2cfcab97363175c58e459f6ff8f9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 23:21:30 -0800 Subject: [PATCH 0236/1326] [var] Whitespace --- src/hb-ot-var-hvar-table.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index 3a2a82037..f9d801e3b 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -78,10 +78,10 @@ struct DeltaSetIndexMap { return (format & 0xF) + 1; } protected: - USHORT format; /* A packed field that describes the compressed + USHORT format; /* A packed field that describes the compressed * representation of delta-set indices. */ - USHORT mapCount; /* The number of mapping entries. */ - BYTE mapData[VAR]; /* The delta-set index mapping data. */ + USHORT mapCount; /* The number of mapping entries. */ + BYTE mapData[VAR]; /* The delta-set index mapping data. */ public: DEFINE_SIZE_ARRAY (4, mapData); From 22af28a3f14c6d748ed589f8980b168152116c8c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Jan 2017 23:42:53 -0800 Subject: [PATCH 0237/1326] [var] Implement MVAR table Unhooked. Untested. --- src/Makefile.sources | 1 + src/hb-font.cc | 2 +- src/hb-ot-var-mvar-table.hh | 110 ++++++++++++++++++++++++++++++++++++ src/hb-ot-var.cc | 1 + 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/hb-ot-var-mvar-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 8d7f1a05d..6363cf930 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -112,6 +112,7 @@ HB_OT_sources = \ hb-ot-var-avar-table.hh \ hb-ot-var-fvar-table.hh \ hb-ot-var-hvar-table.hh \ + hb-ot-var-mvar-table.hh \ $(NULL) HB_OT_headers = \ diff --git a/src/hb-font.cc b/src/hb-font.cc index ea4550126..826d3e1be 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1627,7 +1627,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, } /** - * hb_font_set_var_coords_normalized: + * hb_font_get_var_coords_normalized: * * Return value is valid as long as variation coordinates of the font * are not modified. diff --git a/src/hb-ot-var-mvar-table.hh b/src/hb-ot-var-mvar-table.hh new file mode 100644 index 000000000..3cb749847 --- /dev/null +++ b/src/hb-ot-var-mvar-table.hh @@ -0,0 +1,110 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_VAR_MVAR_TABLE_HH +#define HB_OT_VAR_MVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct VariationValueRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Tag valueTag; /* Four-byte tag identifying a font-wide measure. */ + ULONG varIdx; /* Outer/inner index into VariationStore item. */ + + public: + DEFINE_SIZE_STATIC (8); +}; + + +/* + * MVAR -- Metrics Variations Table + */ + +#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R') + +struct MVAR +{ + static const hb_tag_t tableTag = HB_OT_TAG_MVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + c->check_struct (this) && + valueRecordSize >= VariationValueRecord::static_size && + varStore.sanitize (c, this) && + c->check_array (values, valueRecordSize, valueRecordCount)); + } + + inline float get_var (hb_tag_t tag, + int *coords, unsigned int coord_count) const + { + const VariationValueRecord *record; + record = (VariationValueRecord *) bsearch (&tag, values, + valueRecordCount, valueRecordSize, + (hb_compare_func_t) tag_compare); + if (!record) + return 0.; + + return (this+varStore).get_delta (record->varIdx, coords, coord_count); + } + +protected: + static inline int tag_compare (const hb_tag_t *a, const Tag *b) + { return b->cmp (*a); } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + USHORT reserved; /* Not used; set to 0. */ + USHORT valueRecordSize;/* The size in bytes of each value record — + * must be greater than zero. */ + USHORT valueRecordCount;/* The number of value records — may be zero. */ + OffsetTo + varStore; /* Offset to item variation store table. */ + BYTE values[VAR]; /* Array of value records. The records must be + * in binary order of their valueTag field. */ + + public: + DEFINE_SIZE_ARRAY (12, values); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_MVAR_TABLE_HH */ diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index d4d16dfff..b0d37900e 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -29,6 +29,7 @@ #include "hb-ot-layout-private.hh" #include "hb-ot-var-avar-table.hh" #include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var-mvar-table.hh" #include "hb-ot-var.h" HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) From 72c754873c6b15cecb32d9e491c98495f804347a Mon Sep 17 00:00:00 2001 From: jfkthame Date: Thu, 26 Jan 2017 22:35:41 +0000 Subject: [PATCH 0238/1326] Add Win7 version of himalaya.ttf to the GDEF table blacklist. (#407) --- src/hb-ot-layout.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index d7ededd8d..274f93359 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -111,6 +111,8 @@ _hb_ot_layout_create (hb_face_t *face) || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) + /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ + || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len) /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ From e888f642db16f52836cbfec29de43ff20236dc85 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 26 Jan 2017 14:50:14 -0800 Subject: [PATCH 0239/1326] Route Adlam through Arabic shaper Fixes joined Adlam rendering. Fixes https://github.com/googlei18n/noto-fonts/issues/828 --- src/hb-ot-shape-complex-private.hh | 3 +++ test/shaping/Makefile.am | 1 + ...5dfad7735c6a67085f1b90d4d497e32907db4c78.ttf | Bin 0 -> 21160 bytes test/shaping/tests/arabic-like-joining.tests | 1 + 4 files changed, 5 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/5dfad7735c6a67085f1b90d4d497e32907db4c78.ttf create mode 100644 test/shaping/tests/arabic-like-joining.tests diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index 39572dfe0..952441b6a 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -191,6 +191,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_PSALTER_PAHLAVI: + /* Unicode-9.0 additions */ + case HB_SCRIPT_ADLAM: + /* For Arabic script, use the Arabic shaper even if no OT script tag was found. * This is because we do fallback shaping for Arabic script (and not others). * But note that Arabic shaping is applicable only to horizontal layout; for diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index ea0b28a7e..89578e10b 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -43,6 +43,7 @@ CLEANFILES += \ TESTS = \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ + tests/arabic-like-joining.tests \ tests/automatic-fractions.tests \ tests/cluster.tests \ tests/color-fonts.tests \ diff --git a/test/shaping/fonts/sha1sum/5dfad7735c6a67085f1b90d4d497e32907db4c78.ttf b/test/shaping/fonts/sha1sum/5dfad7735c6a67085f1b90d4d497e32907db4c78.ttf new file mode 100644 index 0000000000000000000000000000000000000000..45f16fc1407aa8066ffa52ecf2fd8a889cbd7093 GIT binary patch literal 21160 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 Date: Wed, 1 Feb 2017 11:57:21 -0800 Subject: [PATCH 0240/1326] Minor Fixes https://github.com/behdad/harfbuzz/issues/411 --- src/hb-fallback-shape.cc | 2 +- src/hb-ot-shape-normalize.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index ac6d4b00f..e5a80ee32 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -125,7 +125,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, pos[i].y_advance = 0; continue; } - font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint); + (void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint); font->get_glyph_advance_for_direction (info[i].codepoint, direction, &pos[i].x_advance, diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 107617e81..94a3d7d27 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -91,7 +91,7 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c, static inline void set_glyph (hb_glyph_info_t &info, hb_font_t *font) { - font->get_nominal_glyph (info.codepoint, &info.glyph_index()); + (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index()); } static inline void From 4ec19319ab195d852708661e12da2a6485fce544 Mon Sep 17 00:00:00 2001 From: jfkthame Date: Thu, 2 Feb 2017 18:48:23 +0000 Subject: [PATCH 0241/1326] Add Win10 Anniversary Update version of Tahoma to GDEF blacklist. (#412) --- src/hb-ot-layout.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 274f93359..580397bd3 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -107,6 +107,10 @@ _hb_ot_layout_create (hb_face_t *face) || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) + /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ + || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len) + /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ + || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len) /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ From 95808bad2c17a9ef41c58c04faf1b4706fb7d72e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 3 Feb 2017 10:39:40 -0800 Subject: [PATCH 0242/1326] Add new API hb_font_set_face() For completeness. --- src/hb-font.cc | 29 +++++++++++++++++++++++++++++ src/hb-font.h | 4 ++++ 2 files changed, 33 insertions(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index 826d3e1be..db3ffcce7 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1371,6 +1371,35 @@ hb_font_get_parent (hb_font_t *font) return font->parent; } +/** + * hb_font_set_face: + * @font: a font. + * @face: new face. + * + * Sets font-face of @font. + * + * Since: 1.4.3 + **/ +void +hb_font_set_face (hb_font_t *font, + hb_face_t *face) +{ + if (font->immutable) + return; + + if (unlikely (!face)) + face = hb_face_get_empty (); + + if (font->face == face) + return; + + hb_face_t *old = font->face; + + font->face = hb_face_reference (face); + + hb_face_destroy (old); +} + /** * hb_font_get_face: * @font: a font. diff --git a/src/hb-font.h b/src/hb-font.h index e2e59796f..85fb56d5b 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -563,6 +563,10 @@ hb_font_set_parent (hb_font_t *font, HB_EXTERN hb_font_t * hb_font_get_parent (hb_font_t *font); +HB_EXTERN void +hb_font_set_face (hb_font_t *font, + hb_face_t *face); + HB_EXTERN hb_face_t * hb_font_get_face (hb_font_t *font); From 2171f48b4b1e66a3c16a83cc00b0006d32ae9738 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 3 Feb 2017 10:58:09 -0800 Subject: [PATCH 0243/1326] Add dirty-state tracking to hb_font_t --- src/hb-font-private.hh | 12 ++++++++++++ src/hb-font.cc | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 53671d78d..fbb16a0b7 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -116,6 +116,16 @@ struct hb_font_t { void *user_data; hb_destroy_func_t destroy; + enum dirty_t { + NOTHING = 0x0000, + FACE = 0x0001, + PARENT = 0x0002, + FUNCS = 0x0004, + SCALE = 0x0008, + PPEM = 0x0010, + VARIATIONS = 0x0020, + } dirty; + struct hb_shaper_data_t shaper_data; @@ -543,6 +553,8 @@ struct hb_font_t { } }; +HB_MARK_AS_FLAG_T (hb_font_t::dirty_t); + #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); #include "hb-shaper-list.hh" diff --git a/src/hb-font.cc b/src/hb-font.cc index db3ffcce7..cc0e6c348 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1196,6 +1196,8 @@ hb_font_get_empty (void) NULL, /* user_data */ NULL, /* destroy */ + hb_font_t::NOTHING, /* dirty_bits */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -1348,6 +1350,11 @@ hb_font_set_parent (hb_font_t *font, if (!parent) parent = hb_font_get_empty (); + if (parent == font->parent) + return; + + font->dirty |= font->PARENT; + hb_font_t *old = font->parent; font->parent = hb_font_reference (parent); @@ -1393,6 +1400,8 @@ hb_font_set_face (hb_font_t *font, if (font->face == face) return; + font->dirty |= font->FACE; + hb_face_t *old = font->face; font->face = hb_face_reference (face); @@ -1446,6 +1455,8 @@ hb_font_set_funcs (hb_font_t *font, if (!klass) klass = hb_font_funcs_get_empty (); + font->dirty |= font->FUNCS; + hb_font_funcs_reference (klass); hb_font_funcs_destroy (font->klass); font->klass = klass; @@ -1501,6 +1512,11 @@ hb_font_set_scale (hb_font_t *font, if (font->immutable) return; + if (font->x_scale == x_scale && font->y_scale == y_scale) + return; + + font->dirty |= font->SCALE; + font->x_scale = x_scale; font->y_scale = y_scale; } @@ -1542,6 +1558,11 @@ hb_font_set_ppem (hb_font_t *font, if (font->immutable) return; + if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) + return; + + font->dirty |= font->PPEM; + font->x_ppem = x_ppem; font->y_ppem = y_ppem; } @@ -1574,6 +1595,15 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, int *coords, /* 2.14 normalized */ unsigned int coords_length) { + if (font->num_coords == coords_length && + 0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0]))) + { + free (coords); + return; + } + + font->dirty |= font->VARIATIONS; + free (font->coords); font->coords = coords; From d3d3691806aaa6aed93a88c845d472e727e7f850 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 3 Feb 2017 15:42:03 -0800 Subject: [PATCH 0244/1326] Add dirty-state tracking to hb_face_t --- src/hb-face-private.hh | 9 +++++++++ src/hb-face.cc | 19 ++++++++++++++++++- src/hb-font.cc | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh index 43e7b1cb3..eb0e850aa 100644 --- a/src/hb-face-private.hh +++ b/src/hb-face-private.hh @@ -54,6 +54,13 @@ struct hb_face_t { mutable unsigned int upem; /* Units-per-EM. */ mutable unsigned int num_glyphs; /* Number of glyphs. */ + enum dirty_t { + NOTHING = 0x0000, + INDEX = 0x0001, + UPEM = 0x0002, + NUM_GLYPHS = 0x0004, + } dirty; + struct hb_shaper_data_t shaper_data; /* Various shaper data. */ /* Various non-shaping data. */ @@ -99,6 +106,8 @@ struct hb_face_t { HB_INTERNAL void load_num_glyphs (void) const; }; +HB_MARK_AS_FLAG_T (hb_face_t::dirty_t); + extern HB_INTERNAL const hb_face_t _hb_face_nil; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/src/hb-face.cc b/src/hb-face.cc index 1ba970707..1800c995a 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -51,6 +51,8 @@ const hb_face_t _hb_face_nil = { 1000, /* upem */ 0, /* num_glyphs */ + hb_face_t::NOTHING, /* dirty */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -171,7 +173,7 @@ hb_face_create (hb_blob_t *blob, closure, (hb_destroy_func_t) _hb_face_for_data_closure_destroy); - hb_face_set_index (face, index); + face->index = index; return face; } @@ -365,6 +367,11 @@ hb_face_set_index (hb_face_t *face, if (face->immutable) return; + if (face->index == index) + return; + + face->dirty |= face->INDEX; + face->index = index; } @@ -400,6 +407,11 @@ hb_face_set_upem (hb_face_t *face, if (face->immutable) return; + if (face->upem == upem) + return; + + face->dirty |= face->UPEM; + face->upem = upem; } @@ -444,6 +456,11 @@ hb_face_set_glyph_count (hb_face_t *face, if (face->immutable) return; + if (face->num_glyphs == glyph_count) + return; + + face->dirty |= face->NUM_GLYPHS; + face->num_glyphs = glyph_count; } diff --git a/src/hb-font.cc b/src/hb-font.cc index cc0e6c348..a08766f5b 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1196,7 +1196,7 @@ hb_font_get_empty (void) NULL, /* user_data */ NULL, /* destroy */ - hb_font_t::NOTHING, /* dirty_bits */ + hb_font_t::NOTHING, /* dirty */ { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, From fc8189b63931f03c5d2e70dde198e9c856bd78f5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 3 Feb 2017 16:17:08 -0800 Subject: [PATCH 0245/1326] Minor --- src/hb-shaper-private.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh index d1d1146da..95358416c 100644 --- a/src/hb-shaper-private.hh +++ b/src/hb-shaper-private.hh @@ -65,9 +65,10 @@ struct hb_shaper_data_t { #define HB_SHAPER_DATA_INVALID ((void *) -1) #define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID) -#define HB_SHAPER_DATA_TYPE(shaper, object) struct hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object) #define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper) -#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE (shaper, object, object) +#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object) #define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create #define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy From 466b3e58bdc64229dab08c6e0e0079c789540370 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 3 Feb 2017 16:43:25 -0800 Subject: [PATCH 0246/1326] Shuffle things around a bit --- src/hb-coretext.cc | 4 ++-- src/hb-directwrite.cc | 4 ++-- src/hb-fallback-shape.cc | 4 ++++ src/hb-graphite2.cc | 4 ++-- src/hb-ot-layout-private.hh | 1 - src/hb-ot-layout.cc | 2 -- src/hb-ot-math.cc | 3 +-- src/hb-ot-shape.cc | 4 ++++ src/hb-ot-var.cc | 2 -- src/hb-shape-plan.cc | 7 ------- src/hb-shaper-private.hh | 11 +++++++---- src/hb-uniscribe.cc | 4 ++-- 12 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index e857dfae0..86de0becf 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -69,8 +69,8 @@ hb_coretext_face_create (CGFontRef cg_font) } -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font) /* diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index d63bc0473..ab07d8a30 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -34,8 +34,8 @@ #define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) #endif -HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, face) -HB_SHAPER_DATA_ENSURE_DECLARE(directwrite, font) +HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, face) +HB_SHAPER_DATA_ENSURE_DEFINE(directwrite, font) /* diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index e5a80ee32..4b60c6c34 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -28,6 +28,10 @@ #include "hb-shaper-impl-private.hh" +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face) +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font) + + /* * shaper face data */ diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index a2d90db87..68f0817d0 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -35,8 +35,8 @@ #include -HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face) -HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font) +HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face) +HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font) /* diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 8c348beb1..071a439d6 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -623,5 +623,4 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props - #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 580397bd3..a1682a5f9 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -39,8 +39,6 @@ #include "hb-ot-map-private.hh" -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) - hb_ot_layout_t * _hb_ot_layout_create (hb_face_t *face) { diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc index 2d7e6792a..f82a07353 100644 --- a/src/hb-ot-math.cc +++ b/src/hb-ot-math.cc @@ -26,10 +26,9 @@ #include "hb-open-type-private.hh" +#include "hb-ot-layout-private.hh" #include "hb-ot-math-table.hh" -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) - static inline const OT::MATH& _get_math (hb_face_t *face) { diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 6b38739c9..2eacb34c4 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -128,6 +128,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, * shaper face data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, face) + hb_ot_shaper_face_data_t * _hb_ot_shaper_face_data_create (hb_face_t *face) { @@ -145,6 +147,8 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data) * shaper font data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, font) + struct hb_ot_shaper_font_data_t {}; hb_ot_shaper_font_data_t * diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc index b0d37900e..691196d9b 100644 --- a/src/hb-ot-var.cc +++ b/src/hb-ot-var.cc @@ -32,8 +32,6 @@ #include "hb-ot-var-mvar-table.hh" #include "hb-ot-var.h" -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) - /* * fvar/avar */ diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 600faaeb1..1ac77bef7 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -35,13 +35,6 @@ #endif -#define HB_SHAPER_IMPLEMENT(shaper) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh index 95358416c..381398a61 100644 --- a/src/hb-shaper-private.hh +++ b/src/hb-shaper-private.hh @@ -71,22 +71,25 @@ struct hb_shaper_data_t { #define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object) #define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create #define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy +#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) hb_##shaper##_shaper_##object##_data_ensure #define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \ HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \ extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \ HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \ extern "C" HB_INTERNAL void \ - HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data) + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \ + extern "C" HB_INTERNAL bool \ + HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object) #define HB_SHAPER_DATA_DESTROY(shaper, object) \ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); -#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \ -static inline bool \ -hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \ +#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \ +bool \ +HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \ {\ retry: \ HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \ diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 6e4db0149..58f983dbe 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -293,8 +293,8 @@ struct range_record_t { unsigned int index_last; /* == end - 1 */ }; -HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face) -HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font) +HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face) +HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font) /* From 73c6dcbb45269186f204b2212288b6384ce42c9d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 7 Feb 2017 16:53:21 -0800 Subject: [PATCH 0247/1326] Silence Coverity warning Fixes https://github.com/behdad/harfbuzz/issues/408 --- src/hb-ot-shape-complex-arabic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 56ec5cd65..57ffc1dc5 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -540,7 +540,7 @@ apply_stch (const hb_ot_shape_plan_t *plan, /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */ hb_position_t extra_repeat_overlap = 0; hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1); - if (shortfall > 0) + if (shortfall > 0 && n_repeating > 0) { ++n_copies; hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining; From 925ceacfed45c44dd2a025c32bebb1358b560741 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 8 Feb 2017 02:17:48 +0000 Subject: [PATCH 0248/1326] util: Add missing field initialisers in constructor (#410) Coverity ID: 141042 --- util/hb-shape.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/hb-shape.cc b/util/hb-shape.cc index 3bd2184de..75c3793b5 100644 --- a/util/hb-shape.cc +++ b/util/hb-shape.cc @@ -35,7 +35,9 @@ struct output_buffer_t format (parser), gs (NULL), line_no (0), - font (NULL) {} + font (NULL), + output_format (HB_BUFFER_SERIALIZE_FORMAT_INVALID), + format_flags (HB_BUFFER_SERIALIZE_FLAG_DEFAULT) {} void init (const font_options_t *font_opts) { From a6ced90efccf869defc0b310effca220f01cf318 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 8 Feb 2017 02:18:33 +0000 Subject: [PATCH 0249/1326] test: Fix some memory leaks in test-font.c (#409) Coverity IDs: 141039, 141040, 141041 --- test/api/test-font.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/test/api/test-font.c b/test/api/test-font.c index 34f6c746e..527dfcdc1 100644 --- a/test/api/test-font.c +++ b/test/api/test-font.c @@ -35,13 +35,23 @@ static const char test_data[] = "test\0data"; static void test_face_empty (void) { + hb_face_t *created_from_empty; + hb_face_t *created_from_null; + g_assert (hb_face_get_empty ()); - g_assert (hb_face_get_empty () != hb_face_create (hb_blob_get_empty (), 0)); - g_assert (hb_face_get_empty () != hb_face_create (NULL, 0)); + + created_from_empty = hb_face_create (hb_blob_get_empty (), 0); + g_assert (hb_face_get_empty () != created_from_empty); + + created_from_null = hb_face_create (NULL, 0); + g_assert (hb_face_get_empty () != created_from_null); g_assert (hb_face_reference_table (hb_face_get_empty (), HB_TAG ('h','e','a','d')) == hb_blob_get_empty ()); g_assert_cmpint (hb_face_get_upem (hb_face_get_empty ()), ==, 1000); + + hb_face_destroy (created_from_null); + hb_face_destroy (created_from_empty); } static void @@ -357,14 +367,29 @@ test_fontfuncs_subclassing (void) static void test_font_empty (void) { + hb_font_t *created_from_empty; + hb_font_t *created_from_null; + hb_font_t *created_sub_from_null; + g_assert (hb_font_get_empty ()); - g_assert (hb_font_get_empty () != hb_font_create (hb_face_get_empty ())); - g_assert (hb_font_get_empty () != hb_font_create (NULL)); - g_assert (hb_font_get_empty () != hb_font_create_sub_font (NULL)); + + created_from_empty = hb_font_create (hb_face_get_empty ()); + g_assert (hb_font_get_empty () != created_from_empty); + + created_from_null = hb_font_create (NULL); + g_assert (hb_font_get_empty () != created_from_null); + + created_sub_from_null = hb_font_create_sub_font (NULL); + g_assert (hb_font_get_empty () != created_sub_from_null); + g_assert (hb_font_is_immutable (hb_font_get_empty ())); g_assert (hb_font_get_face (hb_font_get_empty ()) == hb_face_get_empty ()); g_assert (hb_font_get_parent (hb_font_get_empty ()) == NULL); + + hb_font_destroy (created_sub_from_null); + hb_font_destroy (created_from_null); + hb_font_destroy (created_from_empty); } static void From 09594df1aecbb7d37093055147c25cc7d7b7fef6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 7 Feb 2017 18:25:12 -0800 Subject: [PATCH 0250/1326] Update ax_pthread.m4 to latest upstream version Might help with https://github.com/behdad/harfbuzz/issues/399 --- m4/ax_pthread.m4 | 398 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 287 insertions(+), 111 deletions(-) diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 index d90de34d1..4c4051ea3 100644 --- a/m4/ax_pthread.m4 +++ b/m4/ax_pthread.m4 @@ -19,10 +19,10 @@ # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with +# but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # -# If you are only building threads programs, you may wish to use these +# If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" @@ -30,8 +30,8 @@ # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with @@ -82,35 +82,40 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 18 +#serial 23 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) - AC_MSG_RESULT($ax_pthread_ok) - if test x"$ax_pthread_ok" = xno; then + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -123,7 +128,7 @@ fi # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -132,68 +137,225 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" - ;; - - darwin*) - ax_pthread_flags="-pthread $ax_pthread_flags" + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - case $flag in +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) - AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) - if test x"$ax_pthread_config" = xno; then continue; fi + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -204,7 +366,11 @@ for flag in $ax_pthread_flags; do # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; @@ -213,16 +379,14 @@ for flag in $ax_pthread_flags; do pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) + [ax_pthread_ok=yes], + []) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" - AC_MSG_RESULT($ax_pthread_ok) - if test "x$ax_pthread_ok" = xyes; then - break; - fi + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" @@ -230,76 +394,88 @@ done fi # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT($attr_name) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - ax_cv_PTHREAD_PRIO_INHERIT, [ - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" - # More AIX lossage: must compile with xlc_r or cc_r - if test x"$GCC" != xyes; then - AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) - else - PTHREAD_CC=$CC + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac fi -else - PTHREAD_CC="$CC" fi -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no From ffde3c9f9effcd2b47f5fd76df45551e68c0b1ec Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 8 Feb 2017 21:56:57 +0000 Subject: [PATCH 0251/1326] hb-font: Fix a potentially undefined use of memcmp() (#413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While it’s fine to call memcmp(x, 0, 0) in practice, the C99 standard explicitly says that this is not allowed: even if the length is zero, the pointer arguments must be valid. http://stackoverflow.com/a/16363034 Coverity ID: 141178 Signed-off-by: Philip Withnall --- src/hb-font.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index a08766f5b..e900bd3f6 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1596,7 +1596,8 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, unsigned int coords_length) { if (font->num_coords == coords_length && - 0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0]))) + (coords_length == 0 || + 0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0])))) { free (coords); return; From 7c47474f209bdf84cf87844c277ed711cad78196 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 8 Feb 2017 14:33:28 -0800 Subject: [PATCH 0252/1326] Set LC_ALL instead of LANG when creating harfbuzz.def Hopefully fixes Travis faliure? https://github.com/behdad/harfbuzz/pull/413#issuecomment-278481882 https://travis-ci.org/khaledhosny/harfbuzz/jobs/199785332#L1065 --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index d7420a090..e322d5686 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -218,7 +218,7 @@ harfbuzz.def: $(HBHEADERS) $(HBNODISTHEADERS) (cat $^ || echo 'hb_ERROR ()' ) | \ $(EGREP) '^hb_.* \(' | \ sed -e 's/ (.*//' | \ - LANG=C sort; \ + LC_ALL=C sort; \ echo LIBRARY libharfbuzz-0.dll; \ ) >"$@" @ ! grep -q hb_ERROR "$@" \ From d4bb52b9fd8a5bc4af13752ea3e464eccfe3223b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 9 Feb 2017 14:13:25 -0800 Subject: [PATCH 0253/1326] Unbreak hb-coretext build --- src/hb-coretext.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 86de0becf..8f2483b08 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -1222,6 +1222,9 @@ fail: * AAT shaper */ +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font) + /* * shaper face data */ From 45766b673f427bb791c9d5886cadedfac0447066 Mon Sep 17 00:00:00 2001 From: jfkthame Date: Thu, 16 Feb 2017 17:40:21 +0000 Subject: [PATCH 0254/1326] =?UTF-8?q?[indic]=20Add=20support=20for=20Grant?= =?UTF-8?q?ha=20marks=20that=20may=20be=20used=20in=20Tamil=20to=20th?= =?UTF-8?q?=E2=80=A6=20(#401)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [indic] Add support for Grantha marks that may be used in Tamil to the Indic table. See https://bugzilla.mozilla.org/show_bug.cgi?id=1331339. Testcase: U+0BA4,U+0BC6,U+1133c,U+0BAA,U+1133c,U+0BC6,U+1133c * [indic] Add test for Grantha nukta that is allowed in Tamil by ScriptExtensions.txt --- src/hb-ot-shape-complex-indic-table.cc | 7 +++++++ .../3493e92eaded2661cadde752a39f9d58b11f0326.ttf | Bin 0 -> 1400 bytes test/shaping/tests/indic-script-extensions.tests | 1 + 3 files changed, 8 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/3493e92eaded2661cadde752a39f9d58b11f0326.ttf create mode 100644 test/shaping/tests/indic-script-extensions.tests diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc index 80a6b25e3..e10a4d25f 100644 --- a/src/hb-ot-shape-complex-indic-table.cc +++ b/src/hb-ot-shape-complex-indic-table.cc @@ -422,6 +422,13 @@ hb_indic_get_categories (hb_codepoint_t u) if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u]; break; + case 0x11u: + // According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, + // so the Indic shaper needs to know their categories. + if (unlikely (u == 0x11303)) return _(Vs,R); + if (unlikely (u == 0x1133c)) return _(N,B); + break; + default: break; } diff --git a/test/shaping/fonts/sha1sum/3493e92eaded2661cadde752a39f9d58b11f0326.ttf b/test/shaping/fonts/sha1sum/3493e92eaded2661cadde752a39f9d58b11f0326.ttf new file mode 100644 index 0000000000000000000000000000000000000000..006adb60c9a006efa39b3c23e390894cdfcf8023 GIT binary patch literal 1400 zcmZ8heN0K;8jEXUeiw5G1MzguZXiPK?$U@=O^Ikin-j{pN`JH?2 zz2|rCJr4)~=wJe92sG4r>LC@B0IUP8e8b_EHpl`k;zq>!hPIBHcYj^FgSZoMUQ1i4 z{mQK_69D}d;y~9xFs!*Xc^QB~2p4;UBjI=)cLuf?v8p#Tew=KidQtx!fXeLa33g{s z{MCZ%%h2ZRLqpCbegW~bh^>7Ck+JMO+qsDQ5c8qIt{@4M8N^n^+JWF$81l(I#L|Iz zPXz~hn9W`3c>YDihr@#-5n=V`G{oow9*iVq$E7G_HBbkQa0GxTl+veTE#`s>M-?mB ztLS}Iq{3mNEF7<+5@uT9Oa>EYWDLBHFoZL4O0$kO=uLKX<>;aHlDmhBloTPF^kQ>y zqs7(LKl7r0{G*7!FuOp=dE&M4`cv2aU;a^4b{%S6&V5^UjI)#ZB?1jVq}Z z@=0ao#4+(J6~njLJiGT9^V4=kTV4Lz(p){8X>vZ2Tl|bW^72r*IA3<+=>9K0_l!R7 z%%CjYqKD3@8@x8!zck}xvdD*`r(11t_PE90gku8nAw^^k>=dh(?zNC`$b}QwsjcX@ z^bfaLb*!0L04k16nWEZ*cin_bcq5fzcUI^vW(BKfOlBL4$ziO5oiUO$183nJHrirl zbd-TNGJ=i9Sz53gDXO{jV0F&vl?PL=Q}@O1#M{rU&Wtsc^I28?=|!S`^9IRXK6jv_ zX7arU=dX(QK7OG(%YHO^wVStB7Nqa@P6tlT_g9kTrnBvW_NV8`qc`itKR0TJ-k4u} zyW`~7cRyX2XbxWA7QeX>TVWc*KYlXZ+565fJCjG=|Lod@*3`$mXFXM?PWxOn!>=HT z*xGi{PWDb1)Ce3-!JeMME6fG4wSe2>Bf)cl?G=yD=cx?@Z-6tGxda?>Ye zQn*8r5m?g9#^Z@I)Lw>t=s|za;?saUsW#V{Nl+w5-PMkVm&P);bl@@^V3_O{^fuo06F(I7*Bd?1_x2v3_*Pt)&dAAqRO- Qb@k2dpo;_tLjTOd-{y}g@c;k- literal 0 HcmV?d00001 diff --git a/test/shaping/tests/indic-script-extensions.tests b/test/shaping/tests/indic-script-extensions.tests new file mode 100644 index 000000000..52b6aa0d7 --- /dev/null +++ b/test/shaping/tests/indic-script-extensions.tests @@ -0,0 +1 @@ +fonts/sha1sum/3493e92eaded2661cadde752a39f9d58b11f0326.ttf::U+0BA4,U+0BC6,U+D804,U+DF3C,U+0BAA,U+D804,U+DF3C,U+0BC6,U+D804,U+DF3C:[u0BC6=0+2093|u1133C=0+0|u0BA4=0+1863|u0BC6=3+2093|u1133C=3+0|u0BAA=3+1706|u1133C=3+0] From 44f7d6ecde9bf7427a05cbe73ed5d668b8a72b2a Mon Sep 17 00:00:00 2001 From: jfkthame Date: Fri, 17 Feb 2017 03:03:24 +0000 Subject: [PATCH 0255/1326] Guard against underflow when adjusting length (#421) * Guard against underflow when adjusting length With the fuzz-testcase in mozilla bug 1295299, we end up with a recursed lookup that removes 3 items, when `match_positions[idx]` is 0, which results in (unsigned) `end` wrapping to a huge value. Making `end` a signed int is probably the simplest route to a fix. Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1295299. * Add testcase for #421. --- src/hb-ot-layout-gsubgpos-private.hh | 6 +++--- .../558661aa659912f4d30ecd27bd09835171a8e2b0.ttf | Bin 0 -> 1358 bytes test/shaping/tests/fuzzed.tests | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index b7a0122a3..0c4235268 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -959,7 +959,7 @@ static inline bool apply_lookup (hb_apply_context_t *c, TRACE_APPLY (NULL); hb_buffer_t *buffer = c->buffer; - unsigned int end; + int end; /* All positions are distance from beginning of *output* buffer. * Adjust. */ @@ -998,8 +998,8 @@ static inline bool apply_lookup (hb_apply_context_t *c, /* Recursed lookup changed buffer len. Adjust. */ - end = int (end) + delta; - if (end <= match_positions[idx]) + end += delta; + if (end <= int (match_positions[idx])) { /* End might end up being smaller than match_positions[idx] if the recursed * lookup ended up removing many items, more than we have had matched. diff --git a/test/shaping/fonts/sha1sum/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf b/test/shaping/fonts/sha1sum/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5d72fdfe31f93c74989082bbd274f53c21cc9a39 GIT binary patch literal 1358 zcmeHFF%H5o5c9PWiXy?l#DsVNL*Bpu4?ulD#R`alC-Nvp>9+~2Q=2nwX60+R=R%Q8$Pv0Gt}#&?nI z4I0cyF`jD4GAwJN#Hb{-ngs&)hUD+S?#ZXZBRbyKipJ_fDx5{mx)E}Pf_bI7pln3H g#6zj*;EuCpCPVKF<~5i;5vBxwBmw=wJ_<^G0h}}EQUCw| literal 0 HcmV?d00001 diff --git a/test/shaping/tests/fuzzed.tests b/test/shaping/tests/fuzzed.tests index 771ac2b45..d9bace324 100644 --- a/test/shaping/tests/fuzzed.tests +++ b/test/shaping/tests/fuzzed.tests @@ -10,3 +10,4 @@ fonts/sha1sum/3511ff5c1647150595846ac414c595cccac34f18.ttf:--font-funcs=ot:U+004 fonts/sha1sum/fab39d60d758cb586db5a504f218442cd1395725.ttf:--font-funcs=ot:U+0041,U+0041:[gid0=0+1000|gid0=1+1000] fonts/sha1sum/205edd09bd3d141cc9580f650109556cc28b22cb.ttf:--font-funcs=ot:U+0041:[gid0=0+1000] fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf:--font-funcs=ot:U+0061,U+0061,U+0061:[] +fonts/sha1sum/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf:--font-funcs=ot:U+FFFD,U+E0100,U+FFFD,U+E0010:[] From 70202983f57fe85b2d3b56a9c205effeee66222d Mon Sep 17 00:00:00 2001 From: ebraminio Date: Sat, 18 Feb 2017 10:37:36 +0330 Subject: [PATCH 0256/1326] [ci] Disable vcpkg freetype installation and fix Appveyor CI (#422) --- appveyor.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2a0e7c59f..67f611494 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,18 +32,18 @@ install: - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" - 'if "%compiler%"=="msvc" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' - - 'if "%compiler%"=="msvc" git clone https://github.com/Microsoft/vcpkg' - - 'if "%compiler%"=="msvc" cd vcpkg' - - 'if "%compiler%"=="msvc" powershell -exec bypass scripts\bootstrap.ps1' - - 'if "%compiler%"=="msvc" vcpkg install freetype:%VCPKG_ARCH%' - - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib' - - 'if "%compiler%"=="msvc" cd ..' +# - 'if "%compiler%"=="msvc" git clone https://github.com/Microsoft/vcpkg' +# - 'if "%compiler%"=="msvc" cd vcpkg' +# - 'if "%compiler%"=="msvc" powershell -exec bypass scripts\bootstrap.ps1' +# - 'if "%compiler%"=="msvc" vcpkg install freetype:%VCPKG_ARCH%' +# - 'if "%compiler%"=="msvc" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib' +# - 'if "%compiler%"=="msvc" cd ..' build_script: - 'if "%compiler%"=="msvc" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' - 'if "%compiler%"=="msvc" cd harfbuzz-*\win32' - - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib' - - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 FREETYPE=1 install' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1' # FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib' + - 'if "%compiler%"=="msvc" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 install' # FREETYPE=1 install' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=$MINGW_CHOST --host=$MINGW_CHOST --prefix=$MINGW_PREFIX; make; make check"' From f748e11645a3361f94d6fb10ce59febbaa5ba8ca Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 18 Feb 2017 19:54:33 +0100 Subject: [PATCH 0257/1326] bootstraping structure --- src/Makefile.sources | 1 + src/hb-ot-base-table.hh | 238 ++++++++++++++++++++++++++++++++++++ src/hb-ot-font.cc | 1 + src/hb-ot-layout-private.hh | 2 + 4 files changed, 242 insertions(+) create mode 100644 src/hb-ot-base-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 6363cf930..20ce77b80 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -68,6 +68,7 @@ HB_NODIST_headers = \ HB_FALLBACK_sources = hb-fallback-shape.cc HB_OT_sources = \ + hb-ot-base-table.hh \ hb-ot-font.cc \ hb-ot-layout.cc \ hb-ot-layout-common-private.hh \ diff --git a/src/hb-ot-base-table.hh b/src/hb-ot-base-table.hh new file mode 100644 index 000000000..8ad01fe32 --- /dev/null +++ b/src/hb-ot-base-table.hh @@ -0,0 +1,238 @@ +/* + * Copyright © 2016 Elie Roux + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_OT_BASE_TABLE_HH +#define HB_OT_BASE_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" + +#define HB_OT_TAG_BASE HB_TAG('B','A','S','E') + +// https://www.microsoft.com/typography/otspec/baselinetags.htm + +#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g') +#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b') +#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t') +#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o') +#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b') +#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h') +#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n') + +namespace OT { + +/* + * BASE -- The BASE Table + */ + +struct BaseCoordFormat1 { + protected: + USHORT baseCoordFormat; + SHORT coordinate; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct BaseCoordFormat2 { + protected: + USHORT baseCoordFormat; + SHORT coordinate; + USHORT referenceGlyph; + USHORT baseCoordPoint; + + public: + DEFINE_SIZE_STATIC (8); +}; + +struct BaseCoordFormat3 { + protected: + USHORT baseCoordFormat; + SHORT coordinate; + OffsetTo deviceTable; + + public: + DEFINE_SIZE_STATIC (6); +}; + +struct BaseCoord { + protected: + union { + USHORT baseCoordFormat; + BaseCoordFormat1 format1; + BaseCoordFormat2 format2; + BaseCoordFormat3 format3; + } u; + + public: + DEFINE_SIZE_MIN (4); +}; + +struct FeatMinMaxRecord { + protected: + Tag featureTableTag; + OffsetTo minCoord; + OffsetTo maxCoord; + + public: + DEFINE_SIZE_STATIC (8); + +}; + +struct MinMaxTable { + protected: + OffsetTo minCoord; + OffsetTo maxCoord; + USHORT featMinMaxCount; + ArrayOf featMinMaxRecordTable; + + public: + DEFINE_SIZE_ARRAY (6, featMinMaxRecordTable); + +}; + +struct BaseLangSysRecord { + protected: + Tag baseLangSysTag; + OffsetTo minMax; + + public: + DEFINE_SIZE_STATIC (6); + +}; + +struct BaseValuesTable { + protected: + USHORT defaultIndex; + USHORT baseCoordCount; + ArrayOf baseCoordTable; + + public: + DEFINE_SIZE_ARRAY (4, baseCoordTable); + +}; + +struct BaseScriptTable { + protected: + OffsetTo baseValues; + OffsetTo defaultMinMax; + USHORT baseLangSysCount; + ArrayOf baseLangSysRecordTable; + + public: + DEFINE_SIZE_ARRAY (6, baseLangSysRecordTable); +}; + + +struct BaseScriptRecord { + + protected: + Tag baseScriptTag; + OffsetTo baseScript; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct BaseScriptList { + + protected: + USHORT baseScriptCount; + ArrayOf baseScriptRecordTable; + + public: + DEFINE_SIZE_ARRAY (2, baseScriptRecordTable); + +}; + +struct BaselineTag { + + protected: + Tag tag; + + public: + DEFINE_SIZE_STATIC (4); + +}; + +struct BaseTagList +{ + + protected: + USHORT baseTagCount; + ArrayOf BaseTagListTable; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct VertAxis +{ + + protected: + OffsetTo baseTagList; + OffsetTo baseScriptList; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct HorizAxis +{ + + protected: + OffsetTo baseTagList; + OffsetTo baseScriptList; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct BASE +{ + static const hb_tag_t tableTag = HB_OT_TAG_BASE; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1)); + } + + protected: + FixedVersion<>version; /* Version of the BASE table: 1.0 or 1.1 */ + OffsetTo horizAxis; + OffsetTo vertAxis; + //LOffsetTo itemVarStore; + + public: + DEFINE_SIZE_MIN (6); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_BASE_TABLE_HH */ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 009db20ae..9abdc6757 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -30,6 +30,7 @@ #include "hb-font-private.hh" +#include "hb-ot-base-table.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 071a439d6..ee8e1373e 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -122,6 +122,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, */ namespace OT { + struct BASE; struct GDEF; struct GSUB; struct GPOS; @@ -162,6 +163,7 @@ struct hb_ot_layout_t const struct OT::GPOS *gpos; /* TODO Move the following out of this struct. */ + OT::hb_lazy_table_loader_t base; OT::hb_lazy_table_loader_t math; OT::hb_lazy_table_loader_t fvar; OT::hb_lazy_table_loader_t avar; From d0b97353e930d9b258f42f1cc1ac1a75306b76a8 Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 19 Feb 2017 08:48:22 +0100 Subject: [PATCH 0258/1326] hb-ot-base-table.hh -> hb-ot-layout-base-table.hh per https://github.com/behdad/harfbuzz/issues/418#issuecomment-280873811 --- src/Makefile.sources | 2 +- src/hb-ot-font.cc | 2 +- src/{hb-ot-base-table.hh => hb-ot-layout-base-table.hh} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{hb-ot-base-table.hh => hb-ot-layout-base-table.hh} (100%) diff --git a/src/Makefile.sources b/src/Makefile.sources index 20ce77b80..0f83f6ebd 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -68,9 +68,9 @@ HB_NODIST_headers = \ HB_FALLBACK_sources = hb-fallback-shape.cc HB_OT_sources = \ - hb-ot-base-table.hh \ hb-ot-font.cc \ hb-ot-layout.cc \ + hb-ot-layout-base-table.hh \ hb-ot-layout-common-private.hh \ hb-ot-layout-gdef-table.hh \ hb-ot-layout-gpos-table.hh \ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 9abdc6757..acbda8de5 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -30,7 +30,7 @@ #include "hb-font-private.hh" -#include "hb-ot-base-table.hh" +#include "hb-ot-layout-base-table.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" diff --git a/src/hb-ot-base-table.hh b/src/hb-ot-layout-base-table.hh similarity index 100% rename from src/hb-ot-base-table.hh rename to src/hb-ot-layout-base-table.hh From f131f00b1779b44633223915e17cbce358ad063a Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 19 Feb 2017 10:12:22 +0100 Subject: [PATCH 0259/1326] compile, move into hb-ot-layout.cc --- src/hb-ot-font.cc | 1 - src/hb-ot-layout-base-table.hh | 57 +++++++++++++++++++++++++--------- src/hb-ot-layout.cc | 1 + 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index acbda8de5..009db20ae 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -30,7 +30,6 @@ #include "hb-font-private.hh" -#include "hb-ot-layout-base-table.hh" #include "hb-ot-cmap-table.hh" #include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 8ad01fe32..b3c0927b1 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -109,7 +109,7 @@ struct MinMaxTable { ArrayOf featMinMaxRecordTable; public: - DEFINE_SIZE_ARRAY (6, featMinMaxRecordTable); + DEFINE_SIZE_ARRAY (8, featMinMaxRecordTable); }; @@ -127,10 +127,10 @@ struct BaseValuesTable { protected: USHORT defaultIndex; USHORT baseCoordCount; - ArrayOf baseCoordTable; + OffsetArrayOf baseCoordTable; public: - DEFINE_SIZE_ARRAY (4, baseCoordTable); + DEFINE_SIZE_ARRAY (6, baseCoordTable); }; @@ -142,7 +142,7 @@ struct BaseScriptTable { ArrayOf baseLangSysRecordTable; public: - DEFINE_SIZE_ARRAY (6, baseLangSysRecordTable); + DEFINE_SIZE_ARRAY (8, baseLangSysRecordTable); }; @@ -153,7 +153,7 @@ struct BaseScriptRecord { OffsetTo baseScript; public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_STATIC (6); }; struct BaseScriptList { @@ -163,7 +163,7 @@ struct BaseScriptList { ArrayOf baseScriptRecordTable; public: - DEFINE_SIZE_ARRAY (2, baseScriptRecordTable); + DEFINE_SIZE_ARRAY (4, baseScriptRecordTable); }; @@ -182,10 +182,10 @@ struct BaseTagList protected: USHORT baseTagCount; - ArrayOf BaseTagListTable; + ArrayOf baseTagListTable; public: - DEFINE_SIZE_STATIC (4); + DEFINE_SIZE_ARRAY (4, baseTagListTable); }; struct VertAxis @@ -210,6 +210,32 @@ struct HorizAxis DEFINE_SIZE_STATIC (4); }; + +struct BASEFormat1_1 +{ + + protected: + FixedVersion<>version; + OffsetTo horizAxis; + OffsetTo vertAxis; + LOffsetTo itemVarStore; + + public: + DEFINE_SIZE_STATIC (12); +}; + +struct BASEFormat1_0 +{ + + protected: + FixedVersion<>version; + OffsetTo horizAxis; + OffsetTo vertAxis; + + public: + DEFINE_SIZE_STATIC (8); +}; + struct BASE { static const hb_tag_t tableTag = HB_OT_TAG_BASE; @@ -217,18 +243,19 @@ struct BASE inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (version.sanitize (c) && - likely (version.major == 1)); + return_trace (u.version.sanitize (c) && + likely (u.version.major == 1)); } protected: - FixedVersion<>version; /* Version of the BASE table: 1.0 or 1.1 */ - OffsetTo horizAxis; - OffsetTo vertAxis; - //LOffsetTo itemVarStore; + union { + FixedVersion<>version; /* Version of the BASE table: 1.0 or 1.1 */ + BASEFormat1_0 format1_0; + BASEFormat1_1 format1_1; + } u; public: - DEFINE_SIZE_MIN (6); + DEFINE_SIZE_UNION (4, version); }; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index a1682a5f9..3511810ac 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -31,6 +31,7 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-private.hh" +#include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" From a657f23ca31237d652b5c101ed24194b6aeadaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Mon, 20 Feb 2017 21:52:07 +0200 Subject: [PATCH 0260/1326] Blacklist another instance of Padauk (#419) In https://crbug.com/681813 another instance of Padauk was identified triggering collapsed glyphs. Blacklist this version by patching hb-ot-layout.cc to print out gdef, gsub, and gpos table length, then adding those to the list of blacklisted versions. --- src/hb-ot-layout.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index a1682a5f9..e78e1524e 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -133,6 +133,9 @@ _hb_ot_layout_create (hb_face_t *face) || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) + /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf + * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ + || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len) ) { /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks From 1d30c6d935535743c73b2d18abcc6ae86a1cfc5b Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 25 Feb 2017 16:19:35 +0100 Subject: [PATCH 0261/1326] BASE: sanitize --- src/hb-ot-layout-base-table.hh | 151 ++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index b3c0927b1..691b9db1c 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -48,6 +48,13 @@ namespace OT { */ struct BaseCoordFormat1 { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + protected: USHORT baseCoordFormat; SHORT coordinate; @@ -57,6 +64,13 @@ struct BaseCoordFormat1 { }; struct BaseCoordFormat2 { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + protected: USHORT baseCoordFormat; SHORT coordinate; @@ -68,6 +82,13 @@ struct BaseCoordFormat2 { }; struct BaseCoordFormat3 { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); + } + protected: USHORT baseCoordFormat; SHORT coordinate; @@ -78,6 +99,20 @@ struct BaseCoordFormat3 { }; struct BaseCoord { + + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.baseCoordFormat.sanitize (c)) return_trace (false); + switch (u.baseCoordFormat) { + case 1: return_trace (u.format1.sanitize (c)); + case 2: return_trace (u.format2.sanitize (c)); + case 3: return_trace (u.format3.sanitize (c)); + default:return_trace (true); + } + } + protected: union { USHORT baseCoordFormat; @@ -91,6 +126,15 @@ struct BaseCoord { }; struct FeatMinMaxRecord { + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + minCoord.sanitize (c, base) && + maxCoord.sanitize (c, base)); + } + protected: Tag featureTableTag; OffsetTo minCoord; @@ -102,6 +146,16 @@ struct FeatMinMaxRecord { }; struct MinMaxTable { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + minCoord.sanitize (c, this) && + maxCoord.sanitize (c, this) && + featMinMaxRecordTable.sanitize (c, this)); + } + protected: OffsetTo minCoord; OffsetTo maxCoord; @@ -114,6 +168,14 @@ struct MinMaxTable { }; struct BaseLangSysRecord { + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + minMax.sanitize (c, base)); + } + protected: Tag baseLangSysTag; OffsetTo minMax; @@ -124,6 +186,14 @@ struct BaseLangSysRecord { }; struct BaseValuesTable { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseCoordTable.sanitize (c, this)); + } + protected: USHORT defaultIndex; USHORT baseCoordCount; @@ -135,6 +205,16 @@ struct BaseValuesTable { }; struct BaseScriptTable { + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseValues.sanitize (c, this) && + defaultMinMax.sanitize (c, this) && + baseLangSysRecordTable.sanitize (c, this)); + } + protected: OffsetTo baseValues; OffsetTo defaultMinMax; @@ -148,6 +228,13 @@ struct BaseScriptTable { struct BaseScriptRecord { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseScript.sanitize (c, base)); + } + protected: Tag baseScriptTag; OffsetTo baseScript; @@ -158,6 +245,13 @@ struct BaseScriptRecord { struct BaseScriptList { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseScriptRecordTable.sanitize (c, this)); + } + protected: USHORT baseScriptCount; ArrayOf baseScriptRecordTable; @@ -169,6 +263,12 @@ struct BaseScriptList { struct BaselineTag { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + protected: Tag tag; @@ -180,6 +280,13 @@ struct BaselineTag { struct BaseTagList { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseTagListTable.sanitize (c, this)); + } + protected: USHORT baseTagCount; ArrayOf baseTagListTable; @@ -191,6 +298,14 @@ struct BaseTagList struct VertAxis { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this)); + } + protected: OffsetTo baseTagList; OffsetTo baseScriptList; @@ -202,6 +317,14 @@ struct VertAxis struct HorizAxis { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + baseTagList.sanitize (c, this) && + baseScriptList.sanitize (c, this)); + } + protected: OffsetTo baseTagList; OffsetTo baseScriptList; @@ -214,6 +337,15 @@ struct HorizAxis struct BASEFormat1_1 { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + horizAxis.sanitize (c, this) && + vertAxis.sanitize (c, this) && + itemVarStore.sanitize (c, this)); + } + protected: FixedVersion<>version; OffsetTo horizAxis; @@ -227,6 +359,14 @@ struct BASEFormat1_1 struct BASEFormat1_0 { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + horizAxis.sanitize (c, this) && + vertAxis.sanitize (c, this)); + } + protected: FixedVersion<>version; OffsetTo horizAxis; @@ -240,11 +380,16 @@ struct BASE { static const hb_tag_t tableTag = HB_OT_TAG_BASE; - inline bool sanitize (hb_sanitize_context_t *c) const + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - return_trace (u.version.sanitize (c) && - likely (u.version.major == 1)); + if (!u.version.sanitize (c)) return_trace (false); + if (!likely(u.version.major == 1)) return_trace (false); + switch (u.version.minor) { + case 0: return_trace (u.format1_0.sanitize (c)); + case 1: return_trace (u.format1_1.sanitize (c)); + default:return_trace (true); + } } protected: From a0bdd546c584eb7c7ea3ca7e19a178723e6fe77f Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 25 Feb 2017 16:34:58 +0100 Subject: [PATCH 0262/1326] factorize horiz+vertAxis --- src/hb-ot-layout-base-table.hh | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 691b9db1c..059c8f718 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -100,7 +100,6 @@ struct BaseCoordFormat3 { struct BaseCoord { - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -295,7 +294,7 @@ struct BaseTagList DEFINE_SIZE_ARRAY (4, baseTagListTable); }; -struct VertAxis +struct Axis { inline bool sanitize (hb_sanitize_context_t *c) const @@ -314,26 +313,6 @@ struct VertAxis DEFINE_SIZE_STATIC (4); }; -struct HorizAxis -{ - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baseTagList.sanitize (c, this) && - baseScriptList.sanitize (c, this)); - } - - protected: - OffsetTo baseTagList; - OffsetTo baseScriptList; - - public: - DEFINE_SIZE_STATIC (4); -}; - - struct BASEFormat1_1 { @@ -348,8 +327,8 @@ struct BASEFormat1_1 protected: FixedVersion<>version; - OffsetTo horizAxis; - OffsetTo vertAxis; + OffsetTo horizAxis; + OffsetTo vertAxis; LOffsetTo itemVarStore; public: @@ -369,8 +348,8 @@ struct BASEFormat1_0 protected: FixedVersion<>version; - OffsetTo horizAxis; - OffsetTo vertAxis; + OffsetTo horizAxis; + OffsetTo vertAxis; public: DEFINE_SIZE_STATIC (8); From 499b4bef2a5b6d49374ab4977509d1fbf7bd6038 Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 25 Feb 2017 16:48:22 +0100 Subject: [PATCH 0263/1326] BASE: more consistent naming (with spec and Harfbuzz code base) --- src/hb-ot-layout-base-table.hh | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 059c8f718..f811c4ab2 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -144,7 +144,7 @@ struct FeatMinMaxRecord { }; -struct MinMaxTable { +struct MinMax { inline bool sanitize (hb_sanitize_context_t *c) const { @@ -152,17 +152,17 @@ struct MinMaxTable { return_trace (c->check_struct (this) && minCoord.sanitize (c, this) && maxCoord.sanitize (c, this) && - featMinMaxRecordTable.sanitize (c, this)); + featMinMaxRecords.sanitize (c, this)); } protected: OffsetTo minCoord; OffsetTo maxCoord; USHORT featMinMaxCount; - ArrayOf featMinMaxRecordTable; + ArrayOf featMinMaxRecords; public: - DEFINE_SIZE_ARRAY (8, featMinMaxRecordTable); + DEFINE_SIZE_ARRAY (8, featMinMaxRecords); }; @@ -177,33 +177,33 @@ struct BaseLangSysRecord { protected: Tag baseLangSysTag; - OffsetTo minMax; + OffsetTo minMax; public: DEFINE_SIZE_STATIC (6); }; -struct BaseValuesTable { +struct BaseValues { inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseCoordTable.sanitize (c, this)); + baseCoords.sanitize (c, this)); } protected: USHORT defaultIndex; USHORT baseCoordCount; - OffsetArrayOf baseCoordTable; + OffsetArrayOf baseCoords; public: - DEFINE_SIZE_ARRAY (6, baseCoordTable); + DEFINE_SIZE_ARRAY (6, baseCoords); }; -struct BaseScriptTable { +struct BaseScript { inline bool sanitize (hb_sanitize_context_t *c) const { @@ -211,17 +211,17 @@ struct BaseScriptTable { return_trace (c->check_struct (this) && baseValues.sanitize (c, this) && defaultMinMax.sanitize (c, this) && - baseLangSysRecordTable.sanitize (c, this)); + baseLangSysRecords.sanitize (c, this)); } protected: - OffsetTo baseValues; - OffsetTo defaultMinMax; + OffsetTo baseValues; + OffsetTo defaultMinMax; USHORT baseLangSysCount; - ArrayOf baseLangSysRecordTable; + ArrayOf baseLangSysRecords; public: - DEFINE_SIZE_ARRAY (8, baseLangSysRecordTable); + DEFINE_SIZE_ARRAY (8, baseLangSysRecords); }; @@ -236,7 +236,7 @@ struct BaseScriptRecord { protected: Tag baseScriptTag; - OffsetTo baseScript; + OffsetTo baseScript; public: DEFINE_SIZE_STATIC (6); @@ -248,15 +248,15 @@ struct BaseScriptList { { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseScriptRecordTable.sanitize (c, this)); + baseScriptRecords.sanitize (c, this)); } protected: USHORT baseScriptCount; - ArrayOf baseScriptRecordTable; + ArrayOf baseScriptRecords; public: - DEFINE_SIZE_ARRAY (4, baseScriptRecordTable); + DEFINE_SIZE_ARRAY (4, baseScriptRecords); }; @@ -283,15 +283,15 @@ struct BaseTagList { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - baseTagListTable.sanitize (c, this)); + baselineTags.sanitize (c, this)); } protected: USHORT baseTagCount; - ArrayOf baseTagListTable; + ArrayOf baselineTags; public: - DEFINE_SIZE_ARRAY (4, baseTagListTable); + DEFINE_SIZE_ARRAY (4, baselineTags); }; struct Axis From bd15567ed6a3667e6f8332b7374aece6a6f2361b Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 25 Feb 2017 17:08:01 +0100 Subject: [PATCH 0264/1326] BASE: align member's names --- src/hb-ot-layout-base-table.hh | 70 +++++++++++++++++----------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index f811c4ab2..75b3f2e88 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -57,7 +57,7 @@ struct BaseCoordFormat1 { protected: USHORT baseCoordFormat; - SHORT coordinate; + SHORT coordinate; public: DEFINE_SIZE_STATIC (4); @@ -73,7 +73,7 @@ struct BaseCoordFormat2 { protected: USHORT baseCoordFormat; - SHORT coordinate; + SHORT coordinate; USHORT referenceGlyph; USHORT baseCoordPoint; @@ -90,9 +90,9 @@ struct BaseCoordFormat3 { } protected: - USHORT baseCoordFormat; - SHORT coordinate; - OffsetTo deviceTable; + USHORT baseCoordFormat; + SHORT coordinate; + OffsetTo deviceTable; public: DEFINE_SIZE_STATIC (6); @@ -114,7 +114,7 @@ struct BaseCoord { protected: union { - USHORT baseCoordFormat; + USHORT baseCoordFormat; BaseCoordFormat1 format1; BaseCoordFormat2 format2; BaseCoordFormat3 format3; @@ -135,7 +135,7 @@ struct FeatMinMaxRecord { } protected: - Tag featureTableTag; + Tag featureTableTag; OffsetTo minCoord; OffsetTo maxCoord; @@ -156,9 +156,9 @@ struct MinMax { } protected: - OffsetTo minCoord; - OffsetTo maxCoord; - USHORT featMinMaxCount; + OffsetTo minCoord; + OffsetTo maxCoord; + USHORT featMinMaxCount; ArrayOf featMinMaxRecords; public: @@ -176,8 +176,8 @@ struct BaseLangSysRecord { } protected: - Tag baseLangSysTag; - OffsetTo minMax; + Tag baseLangSysTag; + OffsetTo minMax; public: DEFINE_SIZE_STATIC (6); @@ -194,9 +194,9 @@ struct BaseValues { } protected: - USHORT defaultIndex; - USHORT baseCoordCount; - OffsetArrayOf baseCoords; + USHORT defaultIndex; + USHORT baseCoordCount; + OffsetArrayOf baseCoords; public: DEFINE_SIZE_ARRAY (6, baseCoords); @@ -215,10 +215,10 @@ struct BaseScript { } protected: - OffsetTo baseValues; - OffsetTo defaultMinMax; - USHORT baseLangSysCount; - ArrayOf baseLangSysRecords; + OffsetTo baseValues; + OffsetTo defaultMinMax; + USHORT baseLangSysCount; + ArrayOf baseLangSysRecords; public: DEFINE_SIZE_ARRAY (8, baseLangSysRecords); @@ -235,8 +235,8 @@ struct BaseScriptRecord { } protected: - Tag baseScriptTag; - OffsetTo baseScript; + Tag baseScriptTag; + OffsetTo baseScript; public: DEFINE_SIZE_STATIC (6); @@ -252,7 +252,7 @@ struct BaseScriptList { } protected: - USHORT baseScriptCount; + USHORT baseScriptCount; ArrayOf baseScriptRecords; public: @@ -287,8 +287,8 @@ struct BaseTagList } protected: - USHORT baseTagCount; - ArrayOf baselineTags; + USHORT baseTagCount; + ArrayOf baselineTags; public: DEFINE_SIZE_ARRAY (4, baselineTags); @@ -306,8 +306,8 @@ struct Axis } protected: - OffsetTo baseTagList; - OffsetTo baseScriptList; + OffsetTo baseTagList; + OffsetTo baseScriptList; public: DEFINE_SIZE_STATIC (4); @@ -326,9 +326,9 @@ struct BASEFormat1_1 } protected: - FixedVersion<>version; - OffsetTo horizAxis; - OffsetTo vertAxis; + FixedVersion<> version; + OffsetTo horizAxis; + OffsetTo vertAxis; LOffsetTo itemVarStore; public: @@ -347,9 +347,9 @@ struct BASEFormat1_0 } protected: - FixedVersion<>version; - OffsetTo horizAxis; - OffsetTo vertAxis; + FixedVersion<> version; + OffsetTo horizAxis; + OffsetTo vertAxis; public: DEFINE_SIZE_STATIC (8); @@ -373,9 +373,9 @@ struct BASE protected: union { - FixedVersion<>version; /* Version of the BASE table: 1.0 or 1.1 */ - BASEFormat1_0 format1_0; - BASEFormat1_1 format1_1; + FixedVersion<> version; /* Version of the BASE table: 1.0 or 1.1 */ + BASEFormat1_0 format1_0; + BASEFormat1_1 format1_1; } u; public: From 6685d281d6f50bf046bbfef4a5263e15d15f2f02 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 25 Feb 2017 11:35:05 -0800 Subject: [PATCH 0265/1326] 1.4.3 --- NEWS | 12 ++++++++++++ configure.ac | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 43a3bacea..e175b38a8 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,15 @@ +Overview of changes leading to 1.4.3 +Saturday, February 25, 2017 +==================================== + +- Route Adlam script to Arabic shaper. +- Misc fixes. +- New API: + hb_font_set_face() +- Deprecate API: + hb_graphite2_font_get_gr_font() + + Overview of changes leading to 1.4.2 Monday, January 23, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 31fa97d3b..a3eb0f021 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.2], + [1.4.3], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From d34e35b47457e757781b1769a1fbaf107ec6e32f Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sat, 25 Feb 2017 20:41:05 +0100 Subject: [PATCH 0266/1326] BASE: WIP: more access functions --- src/hb-ot-layout-base-table.hh | 218 +++++++++++++++++++++++++++++---- 1 file changed, 194 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 75b3f2e88..c4d9ad14e 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -43,12 +43,17 @@ namespace OT { +#define NO_COORD -32767 + /* * BASE -- The BASE Table */ struct BaseCoordFormat1 { + inline SHORT get_coord () const + { return coordinate; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -65,6 +70,9 @@ struct BaseCoordFormat1 { struct BaseCoordFormat2 { + inline SHORT get_coord () const + { return coordinate; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -83,6 +91,9 @@ struct BaseCoordFormat2 { struct BaseCoordFormat3 { + inline SHORT get_coord (void ) const + { return coordinate; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -100,6 +111,18 @@ struct BaseCoordFormat3 { struct BaseCoord { + inline hb_position_t get_value (hb_font_t *font, hb_direction_t dir) const + { + SHORT coord; + switch (u.baseCoordFormat) { + case 1: coord = u.format1.get_coord(); + case 2: coord = u.format2.get_coord(); + case 3: coord = u.format3.get_coord(); + default: return 0; + } + return font->em_scale (coord, dir); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -126,6 +149,21 @@ struct BaseCoord { struct FeatMinMaxRecord { + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(minCoord == Null(OffsetTo))) return NO_COORD; + return (this+minCoord).get_value(font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(maxCoord == Null(OffsetTo))) return NO_COORD; + return (this+maxCoord).get_value(font, dir); + } + + inline Tag get_tag () const + { return featureTableTag; } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -146,6 +184,42 @@ struct FeatMinMaxRecord { struct MinMax { + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(minCoord == Null(OffsetTo))) return NO_COORD; + return (this+minCoord).get_value(font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(maxCoord == Null(OffsetTo))) return NO_COORD; + return (this+maxCoord).get_value(font, dir); + } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + { + for (unsigned int i = 0; i < featMinMaxCount; i++) + { + if (featMinMaxRecords[i].get_tag() == featureTableTag) + return featMinMaxRecords[i].get_min_value(font, dir); + // we could take advantage of alphabetical order by comparing Tags, not currently possible + //if (featMinMaxRecords[i].get_tag() > featureTableTag) + // break; + } + return get_min_value (font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + { + for (unsigned int i = 0; i < featMinMaxCount; i++) + { + if (featMinMaxRecords[i].get_tag() == featureTableTag) + return featMinMaxRecords[i].get_max_value(font, dir); + // we could use alphabetical order to break here + } + return get_min_value (font, dir); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -153,13 +227,14 @@ struct MinMax { minCoord.sanitize (c, this) && maxCoord.sanitize (c, this) && featMinMaxRecords.sanitize (c, this)); + // TODO: test alphabetical order? } protected: OffsetTo minCoord; OffsetTo maxCoord; USHORT featMinMaxCount; - ArrayOf featMinMaxRecords; + ArrayOf featMinMaxRecords; /* All FeatMinMaxRecords are listed alphabetically */ public: DEFINE_SIZE_ARRAY (8, featMinMaxRecords); @@ -168,16 +243,32 @@ struct MinMax { struct BaseLangSysRecord { + inline Tag get_tag(void) const + { return baseLangSysTag; } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const + { return (this+minMax).get_min_value(font, dir); } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const + { return (this+minMax).get_max_value(font, dir); } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + { return (this+minMax).get_min_value(font, dir, featureTableTag); } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + { return (this+minMax).get_max_value(font, dir, featureTableTag); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + minMax != Null(OffsetTo) && minMax.sanitize (c, base)); } protected: Tag baseLangSysTag; - OffsetTo minMax; + OffsetTo minMax; // not supposed to be NULL public: DEFINE_SIZE_STATIC (6); @@ -205,6 +296,62 @@ struct BaseValues { struct BaseScript { + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; + return (this+defaultMinMax).get_min_value(font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const + { + if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; + return (this+defaultMinMax).get_max_value(font, dir); + } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const + { + for (unsigned int i = 0; i < baseLangSysCount; i++) + { + if (baseLangSysRecords[i].get_tag() == baseLangSysTag) + return baseLangSysRecords[i].get_min_value(font, dir); + // we could use alphabetical order to break here + } + return get_min_value (font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const + { + for (unsigned int i = 0; i < baseLangSysCount; i++) + { + if (baseLangSysRecords[i].get_tag() == baseLangSysTag) + return baseLangSysRecords[i].get_max_value(font, dir); + // we could use alphabetical order to break here + } + return get_max_value (font, dir); + } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const + { + for (unsigned int i = 0; i < baseLangSysCount; i++) + { + if (baseLangSysRecords[i].get_tag() == baseLangSysTag) + return baseLangSysRecords[i].get_min_value(font, dir, featureTableTag); + // we could use alphabetical order to break here + } + return get_min_value (font, dir); + } + + inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const + { + for (unsigned int i = 0; i < baseLangSysCount; i++) + { + if (baseLangSysRecords[i].get_tag() == baseLangSysTag) + return baseLangSysRecords[i].get_max_value(font, dir); + // we could use alphabetical order to break here + } + return get_max_value (font, dir); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -227,6 +374,16 @@ struct BaseScript { struct BaseScriptRecord { + inline const BaseScript *get_baseScript (void) const + { + return &(this+baseScript); + } + + inline bool get_tag (void) const + { + return baseScriptTag; + } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -244,6 +401,22 @@ struct BaseScriptRecord { struct BaseScriptList { + inline const BaseScript *get_baseScript_from_tag (Tag baseScriptTag) const + { + for (unsigned int i = 0; i < baseScriptCount; i++) + if (baseScriptRecords[i].get_tag() == baseScriptTag) + return baseScriptRecords[i].get_baseScript(); + // we could use alphabetical order to break here + return NULL; + } + + inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseScriptTag) const + { + const BaseScript *baseScript = get_baseScript_from_tag (baseScriptTag); + if (baseScript == NULL) return NO_COORD; + return baseScript->get_min_value(font, dir); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -260,35 +433,26 @@ struct BaseScriptList { }; -struct BaselineTag { +struct BaseTagList +{ - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + inline bool hasTag(Tag tag) const + { + for (unsigned int i = 0; i < baseTagCount; i++) + if (baselineTags[i] == tag) + return true; + return false; + } + + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this)); } protected: - Tag tag; - - public: - DEFINE_SIZE_STATIC (4); - -}; - -struct BaseTagList -{ - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - baselineTags.sanitize (c, this)); - } - - protected: - USHORT baseTagCount; - ArrayOf baselineTags; + USHORT baseTagCount; + ArrayOf baselineTags; // must be in alphabetical order public: DEFINE_SIZE_ARRAY (4, baselineTags); @@ -297,6 +461,12 @@ struct BaseTagList struct Axis { + inline bool hasTag(Tag tag) const + { + if (unlikely(baseTagList == Null(OffsetTo))) return false; + return (this+baseTagList).hasTag(tag); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); From 85630996b8afa699f7b5d19346cdf5c72fcd6e2d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 25 Feb 2017 13:30:38 -0800 Subject: [PATCH 0267/1326] Fix buffer-overrun with Bengali reph positioning code This has no security implications whatsoever since we always keep and extra element at the end of buffer, just in case. Discovered by oss-fuzz CC https://github.com/behdad/harfbuzz/issues/139 Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=660 --- src/hb-ot-shape-complex-indic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index b48fb561c..ec12ce69e 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1497,7 +1497,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (reph_pos == REPH_POS_AFTER_SUB) { new_reph_pos = base; - while (new_reph_pos < end && + while (new_reph_pos + 1 < end && !( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) new_reph_pos++; if (new_reph_pos < end) From a11501444cfc4854bfe2b1d3ce0fc5a957e959d8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 25 Feb 2017 13:37:54 -0800 Subject: [PATCH 0268/1326] Add few tests found by libFuzzer and oss-fuzz --- .../a34a9191d9376bda419836effeef7e75c1386016.ttf | Bin 0 -> 1010 bytes .../a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf | Bin 0 -> 820 bytes .../b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf | Bin 0 -> 3301 bytes .../e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf | Bin 0 -> 515 bytes test/shaping/tests/fuzzed.tests | 4 ++++ 5 files changed, 4 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/a34a9191d9376bda419836effeef7e75c1386016.ttf create mode 100644 test/shaping/fonts/sha1sum/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf create mode 100644 test/shaping/fonts/sha1sum/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf create mode 100644 test/shaping/fonts/sha1sum/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf diff --git a/test/shaping/fonts/sha1sum/a34a9191d9376bda419836effeef7e75c1386016.ttf b/test/shaping/fonts/sha1sum/a34a9191d9376bda419836effeef7e75c1386016.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a358833c2fdcac4574cfcda9e1ea2b663b403573 GIT binary patch literal 1010 zcmb_aO=}ZT6g_VyGntvx5Q>yof<(zGC=`U^LPSGMTm&q%e&EVyCT)V5WSET5W$-`f zs`>-E>QdKkTu5;xQo4}3>7omfBD#?A+?iC}xa$k=<(+%a+jpZs$94#qTg2Bk^dw9Y zMuz!`*x8T-Z=(a^&p_@&zo-4Yf8`5ZJM=I2X(;Te`^1ODwSEw9Uf50yz?~z$G#qzz z{=Cy5zDisU^k&G~JH#u*)sYT*xk}*&F>Ao>a6E~VI$jXJ7C(L_Ng|PC8B!N=P_Xzj zVZ-B{Qn@`;z3Wgq(vRVg!$lpegI=TiG@76o=;#T`v`7?M)6*o^!xA3g8SM`3H@J)R zF3?|LCBn4fLaFDt%<~vNnZzkun7}Y)3$sP5X&k7XlwOs#RP_gtu)LSX{q>tHmd7MQZCG@$s@gCOHMLyLc9s0`6iIbvDEYh5{Qd}PI z^AsS-6@yFbM4rgVTE-?fPH`F}&EIJVqu%;#8gM$(Afn`r9d=13Fzc$kV2N0IXU$$; uCenqmPg9lKcn8RI!&=UrDZQeFU(e>(Cs^aCbGHAx;@$mkA35!Q75EM8ah@;$ literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf b/test/shaping/fonts/sha1sum/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3cd5b5671378c7bb7bec767bbcddb53c89acfbd0 GIT binary patch literal 820 zcmZXS&r1|x7{|Z!&g>8Ohf0kevTTGUh!UfqI!MH#EkU5MYSh7JRcQ^5rrWsr6`{{Dhn-d#$C|8a|L;ljD`z zoP#t^P-|SGp0iX(*0@JrCtFp=E2^C&^HW>o(R!`f@*jhC-4uIJMv5m9?e7398pL@P z;k2rV!w|FY2j1F3u^~F~muUpu(Wp@{SExvBjJ#ULJB!wT@08o6kKuO-MqpOZjBf2I zB0%I)ej;O^HDIMCOXDuC!}9&8d1PwOW1hBc zL-X6dgrG>yI;ZqmB8`zG;|%wZc@5d%px)|beZkuP9{BNfXa!CNYml|oD;{LIM@hx} zMs9Vrwpv!J67Tp>-;k>Y4!^0@mmSYLiNcGiYlWWCeVmrY0iX6iE_U{V&0lZQjjm~O zXcPk@#JrF*!=Fi*dMi5gh9Z|*xd$bKVP{=`xK*;a~<2U?I;_6-{JO<5-Z&MEpnc@BA;n0i4--uK)l5 literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf b/test/shaping/fonts/sha1sum/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf new file mode 100644 index 0000000000000000000000000000000000000000..41897b6934bf75a48bd50dc9852bfc0a6b8dda74 GIT binary patch literal 3301 zcmeHJeN0nV6hHU%wFRuMrIc=Jlz!OihUlOlBB)pjRfj+XKVd-mYMlitt*DGC#OVMX zDvoVVSms9@bB1Mq_z}&R*>rPmb281Ejcke8TogG zx%ZuW?(h75w+{#ajDva*L6O6rmJT<`K7jB>^p-lZvvM47rq}>#ZlVtyIZJJC+&!@v zAfgmN)R>hsO#`44K_9S8- z<4Nk=WzJIAJ~$0PdJ=sWH#)}N7FXc=cC_{G3jc<=M}F_d@d31RJyj*n$U_P}+L+(; z@~X;8r`JhXwCVaWmClMX_Ok34t|vn~(_7{9^Q)m8?R+{83}ga`=ZG7?2vY$_G^;k4 z6$$DDl}@2E=#55;#cVR@v=UX6T52$xED7<^swjz)ymyR57qgxjKL$ElxZPK0T)(l_ zn_rT?YWtZ3$1e8tF*b8|lVzvq&TFmr-v0Xbv`-YxwJQr2SmtT#^LF^!j<;?9oN2`j z7``8X{fQky#MJ;(bOyjR^;WaStWoKt5>_f?#ELpfxh;L!-;tK?`&-#tfsRh@`)y~* z3%OGGl*o+dYL6$UwYFZH-JBg4*pb8MF#R9~P-9#LOvcJ!u;Kk!4F;oCMd&h6v6PJcE3#dEuw=QS}#N9u*H4@eY|kRv@L>O=rock8tq$<~RJ(qE~t+nz3T z*EMsOxgJ^qV7RTpUbv1u5g>EKL`tmO0J*y|cxR%H^Hh?}hk*$WB9^~lUcwwg)I=Q| zWZJWWYcs^1q|49QV`(fhPRI*zE-uciFhkgNUgAbv-g>byo|b+ z^R8S~cF3Dr>^|RulUW^{HgCBi^8JJJXDcnS1%;7{D#AAa@H}J&dnIyl17iTHPt=eY z`ATsQ_KN!ucLQb?@+1Ba{6`4(7*8EJS=NMUA*VK+&@Le72)sAX@IV*22QXk5-H#yw8SZ z$vwrohdL>k2iona%Gsv8Ws!=F`q8Cm7#1tlBj(+InDW@>^4ky7gza5 z$PN?a`?(Y1VyvSPW^q@acw30e zm(%lk)Qf>ItPl?&AY`;cc+pIW(5N%4I4A&+w9;jkNo?(pfuMP;epOp;J>}5bi8CXFg+KIoRND;6IF8*cRsX}CW5`^K- zXnqpRj$$76aD?uep&EbSALA^k@qxYAv%VZMI`%Z~g(cYc!3ww2Qw{~*>M|c}^7?Rg z=z7WP^ZUSC?RA$!W79$ZI@p8*G-7CnbdLjQ(;UNvUwY=yT!7FuL%SI(_^3r|AxADG zLq60%5nQ0oQLYfz=zOd%+=WO4Ob#L~M9~$2Velc~8{{{Ord^_6A!z@5-j0%j5PuBR zBc3x;ZT8$NQzXLLnYbJJd6Fc@&xaBHM6?sf!XRcRK~VZqZ5gRFEG;#HLREt-q9OkC zpmZ4ob{MW&B(EMDC0-n4V`G5n#`3(2H+>3s+!Kyd*Z`hz{Qt}G5qwA9*HG?{BIBP? G#(x4|GIgQ= literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf b/test/shaping/fonts/sha1sum/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e9884ea8556ccad1a61a3e84279be5cfd9249a28 GIT binary patch literal 515 zcmaiwy-ve06orptlRr>Zbqa`~pbRJyBMeLk6(X^KRIxB&0#zeg7lp91vG+mPS$F~- zg#odna_khTLlKUAuYH|+{2fC8XyFMGS9$OF1e;iA<%4rOKR@fAKEH7(+6X$qnk}jrLFyVCgVJcEr73G<=(2HQO4k>ljSM{uF~tkssTA?@a6S*1i2{)Y%nK*c7uD#n!;nCvme>wK zG9g~QZ?}(;;u1nv`kIoz{%p3QbW!NhGUR>!A^H7>Jaouv5e$daCX4qMvgB#lwX}`R om?R0dxbu(+g*A7pHS5oHo0qpvJ6L5O9g=O?pkm;=gGtTw11I%1hyVZp literal 0 HcmV?d00001 diff --git a/test/shaping/tests/fuzzed.tests b/test/shaping/tests/fuzzed.tests index d9bace324..1f51e4412 100644 --- a/test/shaping/tests/fuzzed.tests +++ b/test/shaping/tests/fuzzed.tests @@ -11,3 +11,7 @@ fonts/sha1sum/fab39d60d758cb586db5a504f218442cd1395725.ttf:--font-funcs=ot:U+004 fonts/sha1sum/205edd09bd3d141cc9580f650109556cc28b22cb.ttf:--font-funcs=ot:U+0041:[gid0=0+1000] fonts/sha1sum/217a934cfe15c548b572c203dceb2befdf026462.ttf:--font-funcs=ot:U+0061,U+0061,U+0061:[] fonts/sha1sum/558661aa659912f4d30ecd27bd09835171a8e2b0.ttf:--font-funcs=ot:U+FFFD,U+E0100,U+FFFD,U+E0010:[] +fonts/sha1sum/a34a9191d9376bda419836effeef7e75c1386016.ttf:--font-funcs=ot:U+0041:[] +fonts/sha1sum/a69118c2c2ada48ff803d9149daa54c9ebdae30e.ttf:--font-funcs=ot:U+0041:[gid0=0+1229] +fonts/sha1sum/b6acef662e0beb8d5fcf5b61c6b0ca69537b7402.ttf:--font-funcs=ot:U+0041:[gid0=0+1000] +fonts/sha1sum/e88c339237f52d21e01c55f01b9c1b4cc14a0467.ttf:--font-funcs=ot:U+0041:[gid0=0+1000] From 3963315f1b2eae2504bc683760245c827cd1ef16 Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 26 Feb 2017 15:07:53 +0100 Subject: [PATCH 0269/1326] BASE: first complete version --- src/hb-ot-layout-base-table.hh | 448 +++++++++++++++++++++++---------- 1 file changed, 319 insertions(+), 129 deletions(-) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index c4d9ad14e..9be403e53 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -43,7 +43,9 @@ namespace OT { -#define NO_COORD -32767 +#define NO_COORD Null(SHORT)//SHORT((short int) -32767) + +#define NOT_INDEXED ((unsigned int) -1) /* * BASE -- The BASE Table @@ -51,7 +53,7 @@ namespace OT { struct BaseCoordFormat1 { - inline SHORT get_coord () const + inline SHORT get_coord (void) const { return coordinate; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -70,7 +72,7 @@ struct BaseCoordFormat1 { struct BaseCoordFormat2 { - inline SHORT get_coord () const + inline SHORT get_coord (void) const { return coordinate; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -91,7 +93,7 @@ struct BaseCoordFormat2 { struct BaseCoordFormat3 { - inline SHORT get_coord (void ) const + inline SHORT get_coord (void) const { return coordinate; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -111,17 +113,8 @@ struct BaseCoordFormat3 { struct BaseCoord { - inline hb_position_t get_value (hb_font_t *font, hb_direction_t dir) const - { - SHORT coord; - switch (u.baseCoordFormat) { - case 1: coord = u.format1.get_coord(); - case 2: coord = u.format2.get_coord(); - case 3: coord = u.format3.get_coord(); - default: return 0; - } - return font->em_scale (coord, dir); - } + inline SHORT get_coord (void) const + { return u.format1.get_coord(); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -131,7 +124,7 @@ struct BaseCoord { case 1: return_trace (u.format1.sanitize (c)); case 2: return_trace (u.format2.sanitize (c)); case 3: return_trace (u.format3.sanitize (c)); - default:return_trace (true); + default:return_trace (false); } } @@ -149,16 +142,16 @@ struct BaseCoord { struct FeatMinMaxRecord { - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const - { - if (unlikely(minCoord == Null(OffsetTo))) return NO_COORD; - return (this+minCoord).get_value(font, dir); + inline SHORT get_min_value (void) const + { + if (minCoord == Null(OffsetTo)) return NO_COORD; + return (this+minCoord).get_coord(); } - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const - { - if (unlikely(maxCoord == Null(OffsetTo))) return NO_COORD; - return (this+maxCoord).get_value(font, dir); + inline SHORT get_max_value (void) const + { + if (minCoord == Null(OffsetTo)) return NO_COORD; + return (this+maxCoord).get_coord(); } inline Tag get_tag () const @@ -184,41 +177,39 @@ struct FeatMinMaxRecord { struct MinMax { - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const - { - if (unlikely(minCoord == Null(OffsetTo))) return NO_COORD; - return (this+minCoord).get_value(font, dir); - } - - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const - { - if (unlikely(maxCoord == Null(OffsetTo))) return NO_COORD; - return (this+maxCoord).get_value(font, dir); - } - - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + inline unsigned int get_feature_tag_index (Tag featureTableTag) const { - for (unsigned int i = 0; i < featMinMaxCount; i++) - { - if (featMinMaxRecords[i].get_tag() == featureTableTag) - return featMinMaxRecords[i].get_min_value(font, dir); - // we could take advantage of alphabetical order by comparing Tags, not currently possible - //if (featMinMaxRecords[i].get_tag() > featureTableTag) - // break; + Tag tag; + int cmp; + // taking advantage of alphabetical order + for (unsigned int i = 0; i < featMinMaxCount; i++) { + tag = featMinMaxRecords[i].get_tag(); + cmp = tag.cmp(featureTableTag); + if (cmp == 0) return i; + if (cmp > 0) return NOT_INDEXED; } - return get_min_value (font, dir); + return NOT_INDEXED; } - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const + inline SHORT get_min_value (unsigned int featureTableTagIndex) const { - for (unsigned int i = 0; i < featMinMaxCount; i++) - { - if (featMinMaxRecords[i].get_tag() == featureTableTag) - return featMinMaxRecords[i].get_max_value(font, dir); - // we could use alphabetical order to break here + if (featureTableTagIndex == NOT_INDEXED) { + if (minCoord == Null(OffsetTo)) return NO_COORD; + return (this+minCoord).get_coord(); } - return get_min_value (font, dir); - } + if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD; + return featMinMaxRecords[featureTableTagIndex].get_min_value(); + } + + inline SHORT get_max_value (unsigned int featureTableTagIndex) const + { + if (featureTableTagIndex == NOT_INDEXED) { + if (minCoord == Null(OffsetTo)) return NO_COORD; + return (this+maxCoord).get_coord(); + } + if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD; + return featMinMaxRecords[featureTableTagIndex].get_max_value(); + } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -234,7 +225,7 @@ struct MinMax { OffsetTo minCoord; OffsetTo maxCoord; USHORT featMinMaxCount; - ArrayOf featMinMaxRecords; /* All FeatMinMaxRecords are listed alphabetically */ + ArrayOf featMinMaxRecords; public: DEFINE_SIZE_ARRAY (8, featMinMaxRecords); @@ -246,17 +237,14 @@ struct BaseLangSysRecord { inline Tag get_tag(void) const { return baseLangSysTag; } - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const - { return (this+minMax).get_min_value(font, dir); } + inline unsigned int get_feature_tag_index (Tag featureTableTag) const + { (this+minMax).get_feature_tag_index(featureTableTag); } - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const - { return (this+minMax).get_max_value(font, dir); } + inline SHORT get_min_value (unsigned int featureTableTagIndex) const + { (this+minMax).get_min_value(featureTableTagIndex); } - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const - { return (this+minMax).get_min_value(font, dir, featureTableTag); } - - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const - { return (this+minMax).get_max_value(font, dir, featureTableTag); } + inline SHORT get_max_value (unsigned int featureTableTagIndex) const + { (this+minMax).get_max_value(featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -277,15 +265,25 @@ struct BaseLangSysRecord { struct BaseValues { + inline const unsigned int get_default_base_tag_index (void) const + { return defaultIndex; } + + inline SHORT get_base_coord (unsigned int baselineTagIndex) const + { + if (unlikely(baselineTagIndex >= baseCoordCount)) return NO_COORD; + return (this+baseCoords[baselineTagIndex]).get_coord(); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + defaultIndex <= baseCoordCount && baseCoords.sanitize (c, this)); } protected: - USHORT defaultIndex; + Index defaultIndex; USHORT baseCoordCount; OffsetArrayOf baseCoords; @@ -296,62 +294,56 @@ struct BaseValues { struct BaseScript { - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const + inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const { - if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; - return (this+defaultMinMax).get_min_value(font, dir); - } - - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const - { - if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; - return (this+defaultMinMax).get_max_value(font, dir); - } - - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const - { - for (unsigned int i = 0; i < baseLangSysCount; i++) - { - if (baseLangSysRecords[i].get_tag() == baseLangSysTag) - return baseLangSysRecords[i].get_min_value(font, dir); - // we could use alphabetical order to break here + Tag tag; + int cmp; + for (unsigned int i = 0; i < baseLangSysCount; i++) { + tag = baseLangSysRecords[i].get_tag(); + // taking advantage of alphabetical order + cmp = tag.cmp(baseLangSysTag); + if (cmp == 0) return i; + if (cmp > 0) return NOT_INDEXED; } - return get_min_value (font, dir); + return NOT_INDEXED; } - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const + inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const { - for (unsigned int i = 0; i < baseLangSysCount; i++) - { - if (baseLangSysRecords[i].get_tag() == baseLangSysTag) - return baseLangSysRecords[i].get_max_value(font, dir); - // we could use alphabetical order to break here + if (baseLangSysIndex == NOT_INDEXED) { + if (unlikely(defaultMinMax)) return NOT_INDEXED; + return (this+defaultMinMax).get_feature_tag_index(featureTableTag); } - return get_max_value (font, dir); + if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED; + return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag); } - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const + inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - for (unsigned int i = 0; i < baseLangSysCount; i++) - { - if (baseLangSysRecords[i].get_tag() == baseLangSysTag) - return baseLangSysRecords[i].get_min_value(font, dir, featureTableTag); - // we could use alphabetical order to break here + if (baseLangSysIndex == NOT_INDEXED) { + if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; + return (this+defaultMinMax).get_min_value(featureTableTagIndex); } - return get_min_value (font, dir); + if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD; + return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); } - inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const + inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { - for (unsigned int i = 0; i < baseLangSysCount; i++) - { - if (baseLangSysRecords[i].get_tag() == baseLangSysTag) - return baseLangSysRecords[i].get_max_value(font, dir); - // we could use alphabetical order to break here + if (baseLangSysIndex == NOT_INDEXED) { + if (unlikely(defaultMinMax == Null(OffsetTo))) return NO_COORD; + return (this+defaultMinMax).get_min_value(featureTableTagIndex); } - return get_max_value (font, dir); + if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD; + return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); } + inline unsigned int get_default_base_tag_index (void) const + { return (this+baseValues).get_default_base_tag_index(); } + + inline SHORT get_base_coord (unsigned int baselineTagIndex) const + { return (this+baseValues).get_base_coord(baselineTagIndex); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -374,20 +366,32 @@ struct BaseScript { struct BaseScriptRecord { - inline const BaseScript *get_baseScript (void) const - { - return &(this+baseScript); - } - inline bool get_tag (void) const - { - return baseScriptTag; - } + { return baseScriptTag; } + + inline unsigned int get_default_base_tag_index(void) const + { return (this+baseScript).get_default_base_tag_index(); } + + inline SHORT get_base_coord(unsigned int baselineTagIndex) const + { return (this+baseScript).get_base_coord(baselineTagIndex); } + + inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const + { return (this+baseScript).get_lang_tag_index(baseLangSysTag); } + + inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const + { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); } + + inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); } + + inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && + baseScript != Null(OffsetTo) && baseScript.sanitize (c, base)); } @@ -401,20 +405,48 @@ struct BaseScriptRecord { struct BaseScriptList { - inline const BaseScript *get_baseScript_from_tag (Tag baseScriptTag) const + inline unsigned int get_base_script_index (Tag baseScriptTag) const { for (unsigned int i = 0; i < baseScriptCount; i++) if (baseScriptRecords[i].get_tag() == baseScriptTag) - return baseScriptRecords[i].get_baseScript(); - // we could use alphabetical order to break here - return NULL; + return i; + return NOT_INDEXED; } - inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseScriptTag) const + inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const + { + if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; + return baseScriptRecords[baseScriptIndex].get_default_base_tag_index(); + } + + inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const { - const BaseScript *baseScript = get_baseScript_from_tag (baseScriptTag); - if (baseScript == NULL) return NO_COORD; - return baseScript->get_min_value(font, dir); + if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD; + return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex); + } + + inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { + if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; + return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag); + } + + inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { + if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED; + return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag); + } + + inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD; + return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex); + } + + inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD; + return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -436,12 +468,12 @@ struct BaseScriptList { struct BaseTagList { - inline bool hasTag(Tag tag) const + inline unsigned int get_tag_index(Tag baselineTag) const { for (unsigned int i = 0; i < baseTagCount; i++) - if (baselineTags[i] == tag) - return true; - return false; + if (baselineTags[i] == baselineTag) + return i; + return NOT_INDEXED; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -452,7 +484,7 @@ struct BaseTagList protected: USHORT baseTagCount; - ArrayOf baselineTags; // must be in alphabetical order + SortedArrayOf baselineTags; public: DEFINE_SIZE_ARRAY (4, baselineTags); @@ -461,10 +493,46 @@ struct BaseTagList struct Axis { - inline bool hasTag(Tag tag) const + inline unsigned int get_base_tag_index(Tag baselineTag) const { - if (unlikely(baseTagList == Null(OffsetTo))) return false; - return (this+baseTagList).hasTag(tag); + if (unlikely(baseTagList == Null(OffsetTo))) return NOT_INDEXED; + return (this+baseTagList).get_tag_index(baselineTag); + } + + inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; + return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex); + } + + inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NO_COORD; + return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex); + } + + inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; + return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag); + } + + inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NOT_INDEXED; + return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); + } + + inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NO_COORD; + return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + } + + inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(baseScriptList == Null(OffsetTo))) return NO_COORD; + return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -508,6 +576,104 @@ struct BASEFormat1_1 struct BASEFormat1_0 { + inline bool has_vert_axis(void) + { return vertAxis != Null(OffsetTo); } + + inline bool has_horiz_axis(void) + { return horizAxis != Null(OffsetTo); } + + // horizontal axis base coords: + + inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+horizAxis).get_base_tag_index(baselineTag); + } + + inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); + } + + inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NO_COORD; + return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex); + } + + // vertical axis base coords: + + inline unsigned int get_vert_base_tag_index(Tag baselineTag) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+vertAxis).get_base_tag_index(baselineTag); + } + + inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex); + } + + inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + { + if (vertAxis == Null(OffsetTo)) return NO_COORD; + return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex); + } + + // horizontal axis min/max coords: + + inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); + } + + inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); + } + + inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NO_COORD; + return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + } + + inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(horizAxis == Null(OffsetTo))) return NO_COORD; + return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + } + + // vertical axis min/max coords: + + inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag); + } + + inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NOT_INDEXED; + return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag); + } + + inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NO_COORD; + return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + } + + inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { + if (unlikely(vertAxis == Null(OffsetTo))) return NO_COORD; + return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -529,6 +695,30 @@ struct BASE { static const hb_tag_t tableTag = HB_OT_TAG_BASE; + inline bool has_vert_axis(void) + { return u.format1_0.has_vert_axis(); } + + inline bool has_horiz_axis(void) + { return u.format1_0.has_horiz_axis(); } + + inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const + { return u.format1_0.get_horiz_base_tag_index(baselineTag); } + + inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + { return u.format1_0.get_horiz_default_base_tag_index_for_script_index(baseScriptIndex); } + + inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + { return u.format1_0.get_horiz_base_coord(baseScriptIndex, baselineTagIndex); } + + inline unsigned int get_vert_base_tag_index(Tag baselineTag) const + { return u.format1_0.get_vert_base_tag_index(baselineTag); } + + inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const + { return u.format1_0.get_vert_default_base_tag_index_for_script_index(baseScriptIndex); } + + inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const + { return u.format1_0.get_vert_base_coord(baseScriptIndex, baselineTagIndex); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); @@ -537,7 +727,7 @@ struct BASE switch (u.version.minor) { case 0: return_trace (u.format1_0.sanitize (c)); case 1: return_trace (u.format1_1.sanitize (c)); - default:return_trace (true); + default:return_trace (false); } } From f72726c52b104a71ebf5b39fa1e3eb9febd446fc Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 26 Feb 2017 15:08:43 +0100 Subject: [PATCH 0270/1326] BASE: add function in main BASE object --- src/hb-ot-layout-base-table.hh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index 9be403e53..c60ce6de5 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -719,6 +719,30 @@ struct BASE inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const { return u.format1_0.get_vert_base_coord(baseScriptIndex, baselineTagIndex); } + inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { return u.format1_0.get_horiz_lang_tag_index(baseScriptIndex, baseLangSysTag); } + + inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { return u.format1_0.get_horiz_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); } + + inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return u.format1_0.get_horiz_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } + + inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return u.format1_0.get_horiz_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } + + inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const + { return u.format1_0.get_vert_lang_tag_index(baseScriptIndex, baseLangSysTag); } + + inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const + { return u.format1_0.get_vert_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); } + + inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return u.format1_0.get_vert_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } + + inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const + { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); From b9b005f3a44ccf78a45b212b126287b69b9f4b40 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 1 Mar 2017 14:27:23 -0800 Subject: [PATCH 0271/1326] Fix Context lookup application when moving back after a glyph delete This was broken forever, since days that we did not allow moving tape backwards. Works now. Reported by Doug Felt. --- src/hb-ot-layout-gsubgpos-private.hh | 7 +++---- .../5bbf3712e6f79775c66a4407837a90e591efbef2.ttf | Bin 0 -> 6400 bytes test/shaping/tests/context-matching.tests | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 0c4235268..244c3957a 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -999,14 +999,13 @@ static inline bool apply_lookup (hb_apply_context_t *c, /* Recursed lookup changed buffer len. Adjust. */ end += delta; - if (end <= int (match_positions[idx])) + if (end < int (match_positions[idx])) { /* End might end up being smaller than match_positions[idx] if the recursed - * lookup ended up removing many items, more than we have had matched. + * lookup ended up removing too many items. * Just never rewind end back and get out of here. * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */ end = match_positions[idx]; - /* There can't be any further changes. */ break; } @@ -1019,7 +1018,7 @@ static inline bool apply_lookup (hb_apply_context_t *c, } else { - /* NOTE: delta is negative. */ + /* NOTE: delta is non-positive. */ delta = MAX (delta, (int) next - (int) count); next -= delta; } diff --git a/test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf b/test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2d2bf19b16ff4a4d7c9f4bf0630a4b46167bd048 GIT binary patch literal 6400 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 literal 0 HcmV?d00001 diff --git a/test/shaping/tests/context-matching.tests b/test/shaping/tests/context-matching.tests index e20616e4c..1711818c0 100644 --- a/test/shaping/tests/context-matching.tests +++ b/test/shaping/tests/context-matching.tests @@ -1,3 +1,4 @@ fonts/sha1sum/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+0|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212] fonts/sha1sum/d629e7fedc0b350222d7987345fe61613fa3929a.ttf::U+0915,U+093F,U+0915,U+093F:[ivowelsign03deva=0+530|kadeva=0+1561|ivowelsign03deva=2+530|kadeva=2+1561] fonts/sha1sum/f499fbc23865022234775c43503bba2e63978fe1.ttf::U+09B0,U+09CD,U+09A5,U+09CD,U+09AF,U+09C0:[gid1=0+1320|gid13=0+523|gid18=0+545] +fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf:--font-funcs=ot:U+1F1FA,U+1F1FC:[gid3=0+2550] From 5aec2fb8d0a4db52ae414d980b66018ca5ce1e9c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 2 Mar 2017 11:46:33 -0800 Subject: [PATCH 0272/1326] Remove TODO item that is not going to happen --- src/hb-ot-shape.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 2eacb34c4..29f5e58e5 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -378,7 +378,6 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) post_mask = c->plan->numr_mask | c->plan->frac_mask; } - /* TODO look in pre/post context text also. */ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) From e65aaaa00a3b5ac811b5c73b5186cd7d65731f7b Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 5 Mar 2017 14:53:39 +0100 Subject: [PATCH 0273/1326] BASE: start api --- src/Makefile.sources | 2 ++ src/hb-ot-base.cc | 58 ++++++++++++++++++++++++++++++++++ src/hb-ot-base.h | 56 ++++++++++++++++++++++++++++++++ src/hb-ot-layout-base-table.hh | 15 ++------- 4 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 src/hb-ot-base.cc create mode 100644 src/hb-ot-base.h diff --git a/src/Makefile.sources b/src/Makefile.sources index 0f83f6ebd..db7305659 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -68,6 +68,7 @@ HB_NODIST_headers = \ HB_FALLBACK_sources = hb-fallback-shape.cc HB_OT_sources = \ + hb-ot-base.cc \ hb-ot-font.cc \ hb-ot-layout.cc \ hb-ot-layout-base-table.hh \ @@ -121,6 +122,7 @@ HB_OT_headers = \ hb-ot-font.h \ hb-ot-layout.h \ hb-ot-math.h \ + hb-ot-base.h \ hb-ot-shape.h \ hb-ot-tag.h \ hb-ot-var.h \ diff --git a/src/hb-ot-base.cc b/src/hb-ot-base.cc new file mode 100644 index 000000000..27e0b208a --- /dev/null +++ b/src/hb-ot-base.cc @@ -0,0 +1,58 @@ +/* + * Copyright © 2017 Elie Roux + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#include "hb-open-type-private.hh" + +#include "hb-ot-layout-private.hh" +#include "hb-ot-layout-base-table.hh" + +static inline const OT::BASE& +_get_base (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->base.get ()); +} + +/* + * OT::BASE + */ + +/** + * hb_ot_base_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of an OpenType BASE table on the + * face. + * + * Return value: true if face has a BASE table, false otherwise + * + * Since: XXX + **/ +hb_bool_t +hb_ot_base_has_data (hb_face_t *face) +{ + return &_get_base (face) != &OT::Null(OT::BASE); +} diff --git a/src/hb-ot-base.h b/src/hb-ot-base.h new file mode 100644 index 000000000..9d82d2289 --- /dev/null +++ b/src/hb-ot-base.h @@ -0,0 +1,56 @@ +/* + * Copyright © 2017 Elie Roux + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_OT_H_IN +#error "Include instead." +#endif + +#ifndef HB_OT_BASE_H +#define HB_OT_BASE_H + +#include "hb.h" + +HB_BEGIN_DECLS + +#define HB_OT_TAG_BASE HB_TAG('B','A','S','E') + +// https://www.microsoft.com/typography/otspec/baselinetags.htm + +#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g') +#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b') +#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t') +#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o') +#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b') +#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h') +#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n') + +/* Methods */ + +HB_EXTERN hb_bool_t +hb_ot_base_has_data (hb_face_t *face); + +HB_END_DECLS + +#endif /* HB_OT_BASE_H */ diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh index c60ce6de5..0d1e197e1 100644 --- a/src/hb-ot-layout-base-table.hh +++ b/src/hb-ot-layout-base-table.hh @@ -28,18 +28,7 @@ #include "hb-open-type-private.hh" #include "hb-ot-layout-common-private.hh" - -#define HB_OT_TAG_BASE HB_TAG('B','A','S','E') - -// https://www.microsoft.com/typography/otspec/baselinetags.htm - -#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g') -#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b') -#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t') -#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o') -#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b') -#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h') -#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n') +#include "hb-ot-base.h" namespace OT { @@ -743,7 +732,7 @@ struct BASE inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); } - inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (!u.version.sanitize (c)) return_trace (false); From 3ebcd5a381e2de27a0cfb5af3359331f0b7e7108 Mon Sep 17 00:00:00 2001 From: Elie Roux Date: Sun, 5 Mar 2017 16:26:01 +0100 Subject: [PATCH 0274/1326] first working version! --- src/hb-ot-layout.cc | 2 ++ src/hb-ot.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 3511810ac..d393f5ca6 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -57,6 +57,7 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos = OT::Sanitizer::lock_instance (layout->gpos_blob); layout->math.init (face); + layout->base.init (face); layout->fvar.init (face); layout->avar.init (face); @@ -185,6 +186,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gpos_blob); layout->math.fini (); + layout->base.fini (); layout->fvar.fini (); layout->avar.fini (); diff --git a/src/hb-ot.h b/src/hb-ot.h index 2120a3efa..272208e38 100644 --- a/src/hb-ot.h +++ b/src/hb-ot.h @@ -33,6 +33,7 @@ #include "hb-ot-font.h" #include "hb-ot-layout.h" #include "hb-ot-math.h" +#include "hb-ot-base.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" #include "hb-ot-var.h" From 9ac9af725c781f4597e8db46cf330d595c072739 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 5 Mar 2017 13:51:01 -0800 Subject: [PATCH 0275/1326] Add TODO item --- src/hb-ot-layout-gsubgpos-private.hh | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 244c3957a..005ed21d8 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -996,7 +996,29 @@ static inline bool apply_lookup (hb_apply_context_t *c, if (!delta) continue; - /* Recursed lookup changed buffer len. Adjust. */ + /* Recursed lookup changed buffer len. Adjust. + * + * TODO: + * + * Right now, if buffer length increased by n, we assume n new glyphs + * were added right after the current position, and if buffer length + * was decreased by n, we assume n match positions after the current + * one where removed. The former (buffer length increased) case is + * fine, but the decrease case can be improved in at least two ways, + * both of which are significant: + * + * - If recursed-to lookup is MultipleSubst and buffer length + * decreased, then it's current match position that was deleted, + * NOT the one after it. + * + * - If buffer length was decreased by n, it does not necessarily + * mean that n match positions where removed, as there might + * have been marks and default-ignorables in the sequence. We + * should instead drop match positions between current-position + * and current-position + n instead. + * + * It should be possible to construct tests for both of these cases. + */ end += delta; if (end < int (match_positions[idx])) From 8e42c3cb2bb81351d0a28f213cb4f6d35f4b5e46 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 5 Mar 2017 13:54:56 -0800 Subject: [PATCH 0276/1326] 1.4.4 --- NEWS | 8 ++++++++ configure.ac | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e175b38a8..48a51d68f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +Overview of changes leading to 1.4.4 +Sunday, March 5, 2017 +==================================== + +- Fix Context lookup application when moving back after a glyph deletion. +- Fix buffer-overrun in Bengali. + + Overview of changes leading to 1.4.3 Saturday, February 25, 2017 ==================================== diff --git a/configure.ac b/configure.ac index a3eb0f021..55b48a53b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.3], + [1.4.4], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 3c080a7a0aefec1e9620e3fb399ad280ea4ee5a2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 7 Mar 2017 18:13:28 -0800 Subject: [PATCH 0277/1326] Fix buffer serialize of empty buffer Ouch! --- src/hb-buffer-serialize.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc index 63a0f3466..85696c589 100644 --- a/src/hb-buffer-serialize.cc +++ b/src/hb-buffer-serialize.cc @@ -311,6 +311,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, if (!buf_consumed) buf_consumed = &sconsumed; *buf_consumed = 0; + if (buf_size) + *buf = '\0'; assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); From 47e7a1800fba9b8bf042a1f4976a15ab012ebfc7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 10 Mar 2017 13:23:02 -0800 Subject: [PATCH 0278/1326] Revert "Fix Context lookup application when moving back after a glyph delete" This reverts commit b9b005f3a44ccf78a45b212b126287b69b9f4b40. This introduced invalid access cases. Revert until I fix correctly. --- src/hb-ot-layout-gsubgpos-private.hh | 7 ++++--- .../5bbf3712e6f79775c66a4407837a90e591efbef2.ttf | Bin 6400 -> 0 bytes test/shaping/tests/context-matching.tests | 1 - 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 005ed21d8..f9fcec52b 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -1021,13 +1021,14 @@ static inline bool apply_lookup (hb_apply_context_t *c, */ end += delta; - if (end < int (match_positions[idx])) + if (end <= int (match_positions[idx])) { /* End might end up being smaller than match_positions[idx] if the recursed - * lookup ended up removing too many items. + * lookup ended up removing many items, more than we have had matched. * Just never rewind end back and get out of here. * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */ end = match_positions[idx]; + /* There can't be any further changes. */ break; } @@ -1040,7 +1041,7 @@ static inline bool apply_lookup (hb_apply_context_t *c, } else { - /* NOTE: delta is non-positive. */ + /* NOTE: delta is negative. */ delta = MAX (delta, (int) next - (int) count); next -= delta; } diff --git a/test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf b/test/shaping/fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf deleted file mode 100644 index 2d2bf19b16ff4a4d7c9f4bf0630a4b46167bd048..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6400 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 diff --git a/test/shaping/tests/context-matching.tests b/test/shaping/tests/context-matching.tests index 1711818c0..e20616e4c 100644 --- a/test/shaping/tests/context-matching.tests +++ b/test/shaping/tests/context-matching.tests @@ -1,4 +1,3 @@ fonts/sha1sum/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf::U+1A48,U+1A58,U+1A25,U+1A48,U+1A58,U+1A25,U+1A6E,U+1A63:[uni1A48=0+1212|uni1A25=0+1912|uni1A58=0+0|uni1A48=3+1212|uni1A6E=3+0|uni1A25=3+1912|uni1A58=3+0|uni1A63=3+1212] fonts/sha1sum/d629e7fedc0b350222d7987345fe61613fa3929a.ttf::U+0915,U+093F,U+0915,U+093F:[ivowelsign03deva=0+530|kadeva=0+1561|ivowelsign03deva=2+530|kadeva=2+1561] fonts/sha1sum/f499fbc23865022234775c43503bba2e63978fe1.ttf::U+09B0,U+09CD,U+09A5,U+09CD,U+09AF,U+09C0:[gid1=0+1320|gid13=0+523|gid18=0+545] -fonts/sha1sum/5bbf3712e6f79775c66a4407837a90e591efbef2.ttf:--font-funcs=ot:U+1F1FA,U+1F1FC:[gid3=0+2550] From 60e2586f7652aaa0ee908eb8f54b1498e2ad299e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 10 Mar 2017 23:02:28 -0800 Subject: [PATCH 0279/1326] 1.4.5 --- NEWS | 8 ++++++++ configure.ac | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 48a51d68f..b878793af 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,11 @@ +Overview of changes leading to 1.4.5 +Friday, March 10, 2017 +==================================== + +- Revert "Fix Context lookup application when moving back after a glyph..." + This introduced memory access problems. To be fixed properly soon. + + Overview of changes leading to 1.4.4 Sunday, March 5, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 55b48a53b..91fbfd70b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.4], + [1.4.5], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From f0aa167e447e8aa818a63a4a325be57844bf0353 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Thu, 23 Feb 2017 13:02:49 +0800 Subject: [PATCH 0280/1326] Update Visual Studio builds for UCDN usage We now use UCDN by default, so make it so in the build files; however don't hardcode HAVE_UCDN as one may still opt not to use it (but pass it in as a CFLAG unless one explicitly disables UCDN by using NO_UCDN=1 on the NMake command line). Note that we are not blocking builds where UCDN is disabled along with GLib and ICU, as that will trigger a build error anyways which will tell the user what needs to be done to remedy this. --- win32/README.txt | 6 +++--- win32/config-msvc.mak | 28 ++++++++++++++------------- win32/config.h.win32.in | 2 +- win32/info-msvc.mak | 43 ++++++++++++++++++++++++----------------- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/win32/README.txt b/win32/README.txt index af0dc15c1..dc31e8b6d 100644 --- a/win32/README.txt +++ b/win32/README.txt @@ -36,7 +36,7 @@ PREFIX: Optional. Base directory of where the third-party headers, libraries Explanation of options, set by
    @@ -251,6 +256,7 @@ hb_font_glyph_to_string hb_font_is_immutable hb_font_make_immutable hb_font_reference +hb_font_set_face hb_font_set_funcs hb_font_set_funcs_data hb_font_set_parent @@ -302,6 +308,7 @@ hb_glib_blob_create HB_GOBJECT_TYPE_BLOB HB_GOBJECT_TYPE_BUFFER HB_GOBJECT_TYPE_BUFFER_CONTENT_TYPE +HB_GOBJECT_TYPE_BUFFER_DIFF_FLAGS HB_GOBJECT_TYPE_BUFFER_FLAGS HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FLAGS HB_GOBJECT_TYPE_BUFFER_SERIALIZE_FORMAT @@ -309,6 +316,7 @@ HB_GOBJECT_TYPE_DIRECTION HB_GOBJECT_TYPE_FACE HB_GOBJECT_TYPE_FONT HB_GOBJECT_TYPE_FONT_FUNCS +HB_GOBJECT_TYPE_GLYPH_FLAGS HB_GOBJECT_TYPE_MEMORY_MODE HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS HB_GOBJECT_TYPE_OT_MATH_CONSTANT @@ -328,6 +336,7 @@ HB_GOBJECT_TYPE_SET HB_GOBJECT_TYPE_USER_DATA_KEY hb_gobject_blob_get_type hb_gobject_buffer_content_type_get_type +hb_gobject_buffer_diff_flags_get_type hb_gobject_buffer_flags_get_type hb_gobject_buffer_get_type hb_gobject_buffer_serialize_flags_get_type @@ -336,6 +345,7 @@ hb_gobject_direction_get_type hb_gobject_face_get_type hb_gobject_font_funcs_get_type hb_gobject_font_get_type +hb_gobject_glyph_flags_get_type hb_gobject_memory_mode_get_type hb_gobject_ot_layout_glyph_class_get_type hb_gobject_ot_math_constant_get_type diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index a25a2cb67..a45062aa5 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1413,7 +1413,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, /** * hb_glyph_info_get_glyph_flags: - * @buffer: a #hb_glyph_info_t. + * @info: a #hb_glyph_info_t. * * Returns glyph flags encoded within a #hb_glyph_info_t. * @@ -1882,6 +1882,12 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g * Comparing buffers. */ +/** + * hb_buffer_diff: + * + * + * Since: 1.5.0 + **/ hb_buffer_diff_flags_t hb_buffer_diff (hb_buffer_t *buffer, hb_buffer_t *reference, From e8b364b86023731e0416ab4eb433467c4b7a0ec2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 23 Aug 2017 15:00:45 -0700 Subject: [PATCH 0375/1326] 1.5.0 --- NEWS | 44 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b058bad3c..3a3962bcf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,47 @@ +Overview of changes leading to 1.5.0 +Wednesday, August 23, 2017 +==================================== + +- Misc new API, for appending a buffer to another, and for comparing + contents of two buffers for types of differences. + +- New "unsafe-to-break" API. Can be used to speed up reshaping + in line-breaking situations. Essentially, after shaping, it returns + positions in the input string (some of the cluster boundaries) that + are "safe to break" in that if the text is segmented at that position + and two sides reshaped and concatenated, the shaping result is + exactly the same as shaping the text in one piece. + + hb-view and hb-shape and hb-shape now take --verify, which verifies + the above property. + + Some corner cases of the implementation are still not quite working. + Those will be fixed in subsequent releases. + +- New API: + +hb_buffer_append() + +hb_glyph_flags_t +HB_GLYPH_FLAG_UNSAFE_TO_BREAK +HB_GLYPH_FLAG_DEFINED +hb_glyph_info_get_glyph_flags() + +HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS + +hb_buffer_diff_flags_t +HB_BUFFER_DIFF_FLAG_EQUAL +HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH +HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH +HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT +HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT +HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH +HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH +HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH +HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH +hb_buffer_diff + + Overview of changes leading to 1.4.8 Tuesday, August 8, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 52134c877..82895eab9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.4.8], + [1.5.0], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 099472e08bf81d6dd8ca1647999592df6b7fdfb9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Aug 2017 16:45:06 -0700 Subject: [PATCH 0376/1326] hb_buffer_diff() tweak I like to have a mode where CONTAINS_NOTDEF and CONTAINS_DOTTEDCIRCLE are not returned. Abused a value of -1 for that. hb-shape now uses it. Fixes two of the six tests failing with --verify in test/shaping/run-tests.sh. --- src/hb-buffer.cc | 16 ++++++++-------- test/shaping/run-tests.sh | 4 ++-- util/options.hh | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index a45062aa5..6b05d3a6a 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -31,10 +31,6 @@ #include "hb-utf-private.hh" -#ifndef HB_DEBUG_BUFFER -#define HB_DEBUG_BUFFER (HB_DEBUG+0) -#endif - /** * SECTION: hb-buffer * @title: Buffers @@ -1885,6 +1881,9 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g /** * hb_buffer_diff: * + * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT + * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most + * callers if just comparing two buffers is needed. * * Since: 1.5.0 **/ @@ -1898,6 +1897,7 @@ hb_buffer_diff (hb_buffer_t *buffer, return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH; hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL; + bool contains = dottedcircle_glyph != (hb_codepoint_t) -1; unsigned int count = reference->len; @@ -1911,9 +1911,9 @@ hb_buffer_diff (hb_buffer_t *buffer, unsigned int i; for (i = 0; i < count; i++) { - if (info[i].codepoint == dottedcircle_glyph) + if (contains && info[i].codepoint == dottedcircle_glyph) result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; - else if (info[i].codepoint == 0) + if (contains && info[i].codepoint == 0) result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; } result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH; @@ -1933,9 +1933,9 @@ hb_buffer_diff (hb_buffer_t *buffer, result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH; if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED)) result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH; - if (ref_info->codepoint == dottedcircle_glyph) + if (contains && ref_info->codepoint == dottedcircle_glyph) result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; - else if (ref_info->codepoint == 0) + if (contains && ref_info->codepoint == 0) result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; buf_info++; ref_info++; diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh index 9c4963148..2b10e7c83 100755 --- a/test/shaping/run-tests.sh +++ b/test/shaping/run-tests.sh @@ -4,8 +4,8 @@ test "x$srcdir" = x && srcdir=. test "x$builddir" = x && builddir=. test "x$top_builddir" = x && top_builddir=../.. -#hb_shape="$top_builddir/util/hb-shape$EXEEXT --verify" -hb_shape="$top_builddir/util/hb-shape$EXEEXT" +hb_shape="$top_builddir/util/hb-shape$EXEEXT --verify" +#hb_shape="$top_builddir/util/hb-shape$EXEEXT" fails=0 diff --git a/util/options.hh b/util/options.hh index dbc4eaf94..9ad2225d5 100644 --- a/util/options.hh +++ b/util/options.hh @@ -409,7 +409,7 @@ struct shape_options_t : option_group_t } bool ret = true; - hb_buffer_diff_flags_t diff = hb_buffer_diff (buffer, reconstruction, 0, 0); + hb_buffer_diff_flags_t diff = hb_buffer_diff (buffer, reconstruction, (hb_codepoint_t) -1, 0); if (diff) { if (error) From 69d701b02e5ebc3597b0d0576dbab8e1ece51944 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Aug 2017 17:07:29 -0700 Subject: [PATCH 0377/1326] [util] When --verify fails, return reconstructed shape results --- util/options.hh | 8 +++----- util/view-cairo.hh | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/util/options.hh b/util/options.hh index 9ad2225d5..42bb8c46e 100644 --- a/util/options.hh +++ b/util/options.hh @@ -416,11 +416,9 @@ struct shape_options_t : option_group_t *error = "Safe-to-break test failed."; ret = false; - if (0) - { - hb_buffer_set_length (buffer, 0); - hb_buffer_append (buffer, reconstruction, 0, -1); - } + /* Return the reconstructed result instead so it can be inspected. */ + hb_buffer_set_length (buffer, 0); + hb_buffer_append (buffer, reconstruction, 0, -1); } hb_buffer_destroy (reconstruction); diff --git a/util/view-cairo.hh b/util/view-cairo.hh index d3e59afa5..bf56da3c8 100644 --- a/util/view-cairo.hh +++ b/util/view-cairo.hh @@ -59,7 +59,7 @@ struct view_cairo_t } void error (const char *message) { - fail (false, "%s", message); + g_printerr ("%s: %s\n", g_get_prgname (), message); } void consume_glyphs (hb_buffer_t *buffer, const char *text, From b262ebcc9c9539076d17751e9bae06a8fd5001ff Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Aug 2017 17:25:10 -0700 Subject: [PATCH 0378/1326] [util] Fix cluster sweeping during --verify If *I* get this wrong in 2017, I have no idea how others get their head around cluster math... Fixes tests/arabic-fallback-shaping.tests --- util/options.hh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/util/options.hh b/util/options.hh index 42bb8c46e..b24ab0c8e 100644 --- a/util/options.hh +++ b/util/options.hh @@ -366,13 +366,18 @@ struct shape_options_t : option_group_t } else { - unsigned int cluster = info[end].cluster; if (forward) - while (text_end < num_chars && text[text_end].cluster != cluster) + { + unsigned int cluster = info[end].cluster; + while (text_end < num_chars && text[text_end].cluster < cluster) text_end++; + } else - while (text_start && text[text_start - 1].cluster != cluster) + { + unsigned int cluster = info[end - 1].cluster; + while (text_start && text[text_start - 1].cluster >= cluster) text_start--; + } } assert (text_start < text_end); From c449d2d8c9e27502380faa0b568a374c838ac9a7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Aug 2017 17:28:22 -0700 Subject: [PATCH 0379/1326] [unsafe-to-break] Mark during fraction-slash formation Fixes tests/automatic-fractions.tests --- src/hb-ot-shape.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index bc5366969..54c33a3e1 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -394,6 +394,8 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) end++; + buffer->unsafe_to_break (start, end); + for (unsigned int j = start; j < i; j++) info[j].mask |= pre_mask; info[i].mask |= c->plan->frac_mask; From 06cb162cd79cc922b572e5f532ca867223b6dc4c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Sep 2017 10:34:21 -0700 Subject: [PATCH 0380/1326] [indic] Treat Consonant_With_Stacker as consonant Fixes https://github.com/behdad/harfbuzz/issues/528 "Kannada JIHVAMULIYA and UPADHMANIYA insert dotted circles" --- src/hb-ot-shape-complex-indic-private.hh | 2 +- .../3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf | Bin 0 -> 988 bytes test/shaping/tests/indic-syllable.tests | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh index 58be42224..c880311ee 100644 --- a/src/hb-ot-shape-complex-indic-private.hh +++ b/src/hb-ot-shape-complex-indic-private.hh @@ -121,7 +121,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, - INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */ + INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_C, INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, diff --git a/test/shaping/fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf b/test/shaping/fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d7db1de2b0df348eb7d9f72d75422b51adada9a4 GIT binary patch literal 988 zcmZ{jT}YEr7{~wTea~L!+@|I>OU?G-M^U6sH%k`Smx~Hlj=&($<($*pTyDXFF1oT0 z3JNMIB8BoMA}PWkywJKdE4&N3iy%lyjqpO($zb!^CCb zNFtfLn~8j<#Q5I6jsO~PiMWJV8wn(1C}O86*D|p+8i;iAclt4^w~@Fx))!BtyAdK5 z`K+`?%FPe)9%RFWEi{gqZ7#-KHZ!Yt*DDT(z0y)xkfmg~Yi-WLib`paJzM(7Mp9Av zTgvpfwAgy`Q){uQ;^E6mdr>pb}%iIp0tR z1^WTb1l7zzAsnbeHEO7`(_%I$4ts^G&RyViyXq<&cExP6{7;t)*v$t|$L`-9eKFYD z*5+?*YnONZA*|@+zVVTviC2$?U$0D^?FhzW!Onik^|vNhFWsRX5oa%B7&=T)6ZHF$ zR$1(~@G#w;rYn2Dw&i+$B1fynP3M1pBaE4?Q*+BLOOu8nB}tgQmWfYel6S+V$g~HP zLrE@;0*2?yEva$C&{~w5N^~+fUt~9+q5Zn2sil$^GGFN`LQ(^rdX7fo8ZJp3jq9US z!|U^T(Wsx-FJx*cNq(Fh>WX-eW`JyQ`a+RaRS!-I{S5R{lzt(drhY!1{*kBp$wl{| zR77*J9y@Wymgu(F(TqMMs9E7h08zxrI-*)p>Vwo;(1|XbLoeC=>S&P@>5%vz|M^JJ pLZW%B%`g+hsJb`{nx)!wbRUhY(JxHtd+ literal 0 HcmV?d00001 diff --git a/test/shaping/tests/indic-syllable.tests b/test/shaping/tests/indic-syllable.tests index 26c38b35b..37eaadcd5 100644 --- a/test/shaping/tests/indic-syllable.tests +++ b/test/shaping/tests/indic-syllable.tests @@ -1 +1,2 @@ -fonts/sha1sum/54674a3111d209fb6be0ed31745314b7a8d2c244.ttf::U+0BA4,U+0BCD,U+00B3:[taprehalftamil=0+1509|uni00B3=2+674] +fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF1:[gid1=0+1129] +fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF2:[gid2=0+1539] From 04f009f84891b513087830c7aa1b755addd016d9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Sep 2017 10:38:25 -0700 Subject: [PATCH 0381/1326] Add test accidentally removed in previous commit --- test/shaping/tests/indic-syllable.tests | 1 + 1 file changed, 1 insertion(+) diff --git a/test/shaping/tests/indic-syllable.tests b/test/shaping/tests/indic-syllable.tests index 37eaadcd5..ecaad906b 100644 --- a/test/shaping/tests/indic-syllable.tests +++ b/test/shaping/tests/indic-syllable.tests @@ -1,2 +1,3 @@ +fonts/sha1sum/54674a3111d209fb6be0ed31745314b7a8d2c244.ttf::U+0BA4,U+0BCD,U+00B3:[taprehalftamil=0+1509|uni00B3=2+674] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF1:[gid1=0+1129] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF2:[gid2=0+1539] From 3e1fc6d18ba0019bbeede78b95070a6e7156c314 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Sep 2017 10:46:48 -0700 Subject: [PATCH 0382/1326] Minor --- test/shaping/run-tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh index 2b10e7c83..9f3654506 100755 --- a/test/shaping/run-tests.sh +++ b/test/shaping/run-tests.sh @@ -23,10 +23,10 @@ for f in "$@"; do $reference || echo "Running tests in $f" while IFS=: read fontfile options unicodes glyphs_expected; do if echo "$fontfile" | grep -q '^#'; then - $reference || echo "Skipping $fontfile:$unicodes" + $reference || echo "#hb-shape $fontfile --unicodes $unicodes" continue fi - $reference || echo "Testing $fontfile:$unicodes" + $reference || echo "hb-shape $fontfile --unicodes $unicodes" glyphs=`$srcdir/hb-unicode-encode "$unicodes" | $hb_shape $options "$srcdir/$fontfile"` if test $? != 0; then echo "hb-shape failed." >&2 From 0e5b475d98dd67e927534508fe2cd8dc9765e24e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Sep 2017 18:28:47 -0700 Subject: [PATCH 0383/1326] Minor --- test/shaping/run-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh index 9f3654506..c6b35e31e 100755 --- a/test/shaping/run-tests.sh +++ b/test/shaping/run-tests.sh @@ -23,7 +23,7 @@ for f in "$@"; do $reference || echo "Running tests in $f" while IFS=: read fontfile options unicodes glyphs_expected; do if echo "$fontfile" | grep -q '^#'; then - $reference || echo "#hb-shape $fontfile --unicodes $unicodes" + $reference || echo "# hb-shape $fontfile --unicodes $unicodes" continue fi $reference || echo "hb-shape $fontfile --unicodes $unicodes" From 03a5a6f873e5a50011f1c2418f5ceab86d9c2931 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 1 Sep 2017 19:09:54 -0700 Subject: [PATCH 0384/1326] [util] Add --unicodes to hb-view / hb-shape Fixes https://github.com/behdad/harfbuzz/issues/154 --- test/shaping/hb_test_tools.py | 2 +- util/options.cc | 65 ++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/test/shaping/hb_test_tools.py b/test/shaping/hb_test_tools.py index 052974dee..b9cb836a5 100644 --- a/test/shaping/hb_test_tools.py +++ b/test/shaping/hb_test_tools.py @@ -461,7 +461,7 @@ class Unicode: @staticmethod def parse (s): s = re.sub (r"0[xX]", " ", s) - s = re.sub (r"[<+>{},;&#\\xXuUnNiI\n ]", " ", s) + s = re.sub (r"[<+>{},;&#\\xXuUnNiI\n\t]", " ", s) return [int (x, 16) for x in s.split ()] @staticmethod diff --git a/util/options.cc b/util/options.cc index b1a83edcb..1abafdaa7 100644 --- a/util/options.cc +++ b/util/options.cc @@ -299,6 +299,68 @@ parse_variations (const char *name G_GNUC_UNUSED, return true; } +static gboolean +parse_text (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + text_options_t *text_opts = (text_options_t *) data; + + if (text_opts->text) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text or --unicodes can be provided but not both"); + return false; + } + + text_opts->text = g_strdup (arg); + return true; +} + + +static gboolean +parse_unicodes (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + text_options_t *text_opts = (text_options_t *) data; + + if (text_opts->text) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text or --unicodes can be provided but not both"); + return false; + } + + GString *gs = g_string_new (NULL); + char *s = (char *) arg; + char *p; + + while (s && *s) + { + while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t", *s)) + s++; + + errno = 0; + hb_codepoint_t u = strtoul (s, &p, 16); + if (errno || s == p) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing Unicode values at: '%s'", s); + return false; + } + + g_string_append_unichar (gs, u); + + s = p; + } + + text_opts->text = g_string_free (gs, FALSE); + return true; +} + void view_options_t::add_options (option_parser_t *parser) @@ -491,8 +553,9 @@ text_options_t::add_options (option_parser_t *parser) { GOptionEntry entries[] = { - {"text", 0, 0, G_OPTION_ARG_STRING, &this->text, "Set input text", "string"}, + {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"}, {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name\n\n If no text is provided, standard input is used for input.\n", "filename"}, + {"unicodes", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"}, {"text-before", 0, 0, G_OPTION_ARG_STRING, &this->text_before, "Set text context before each line", "string"}, {"text-after", 0, 0, G_OPTION_ARG_STRING, &this->text_after, "Set text context after each line", "string"}, {NULL} From 61a9d7e6d0e6df7b48f58fa1679f0f93407993b2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 4 Sep 2017 19:48:52 -0700 Subject: [PATCH 0385/1326] Minor --- test/shaping/run-tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/shaping/run-tests.sh b/test/shaping/run-tests.sh index c6b35e31e..a7d331aa2 100755 --- a/test/shaping/run-tests.sh +++ b/test/shaping/run-tests.sh @@ -26,12 +26,12 @@ for f in "$@"; do $reference || echo "# hb-shape $fontfile --unicodes $unicodes" continue fi - $reference || echo "hb-shape $fontfile --unicodes $unicodes" - glyphs=`$srcdir/hb-unicode-encode "$unicodes" | $hb_shape $options "$srcdir/$fontfile"` + $reference || echo "hb-shape $fontfile $options --unicodes $unicodes" + glyphs=`$hb_shape "$srcdir/$fontfile" $options --unicodes "$unicodes"` if test $? != 0; then echo "hb-shape failed." >&2 fails=$((fails+1)) - continue + #continue fi if $reference; then echo "$fontfile:$options:$unicodes:$glyphs" From 7cc348041d0b026ca6d2c240134e8f9100600e99 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 4 Sep 2017 20:04:59 -0700 Subject: [PATCH 0386/1326] [unsafe-to-break] Fix unsafe-to-break for cluster-level=1 Fixes tests/shaping/tests/cluster.tests --- src/hb-ot-shape.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 54c33a3e1..8cd8fcc17 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -275,8 +275,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) static void hb_form_clusters (hb_buffer_t *buffer) { - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ @@ -288,11 +287,17 @@ hb_form_clusters (hb_buffer_t *buffer) if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && !_hb_glyph_info_is_joiner (&info[i]))) { - buffer->merge_clusters (base, i); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, i); + else + buffer->unsafe_to_break (base, i); base = i; } } - buffer->merge_clusters (base, count); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, count); + else + buffer->unsafe_to_break (base, count); } static void @@ -580,8 +585,6 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; - hb_ot_shape_initialize_masks (c); - hb_ot_mirror_chars (c); HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); @@ -836,8 +839,10 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->clear_output (); + hb_ot_shape_initialize_masks (c); hb_set_unicode_props (c->buffer); hb_insert_dotted_circle (c->buffer, c->font); + hb_form_clusters (c->buffer); hb_ensure_native_direction (c->buffer); From d03f11f246efec13e48fd68a9ce136db771b22bf Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 4 Sep 2017 20:14:13 -0700 Subject: [PATCH 0387/1326] Fix buffer_diff for empty buffers If buffers are empty, content type should be ignored. This fixes last of the failing tests: fuzzed.tests. Green again! --- src/hb-buffer.cc | 2 +- src/hb-buffer.h | 4 ++-- util/options.hh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 6b05d3a6a..171d1016e 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1893,7 +1893,7 @@ hb_buffer_diff (hb_buffer_t *buffer, hb_codepoint_t dottedcircle_glyph, unsigned int position_fuzz) { - if (buffer->content_type != reference->content_type) + if (buffer->content_type != reference->content_type && buffer->len && reference->len) return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH; hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL; diff --git a/src/hb-buffer.h b/src/hb-buffer.h index ffbf66ee1..1d633f7dc 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -481,12 +481,12 @@ typedef enum { /*< flags >*/ /* Buffers with different content_type cannot be meaningfully compared * in any further detail. */ - HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0X0001, + HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001, /* For buffers with differing length, the per-glyph comparison is not * attempted, though we do still scan reference for dottedcircle / .notdef * glyphs. */ - HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0X0002, + HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002, /* We want to know if dottedcircle / .notdef glyphs are present in the * reference, as we may not care so much about other differences in this diff --git a/util/options.hh b/util/options.hh index b24ab0c8e..9feee2dc0 100644 --- a/util/options.hh +++ b/util/options.hh @@ -414,7 +414,7 @@ struct shape_options_t : option_group_t } bool ret = true; - hb_buffer_diff_flags_t diff = hb_buffer_diff (buffer, reconstruction, (hb_codepoint_t) -1, 0); + hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0); if (diff) { if (error) From a984e0c4d921a6dff82cc1b5c686cc957215bc7e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 5 Sep 2017 11:18:35 -0700 Subject: [PATCH 0388/1326] 1.5.1 --- NEWS | 13 +++++++++++++ configure.ac | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 3a3962bcf..92e5a5370 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,16 @@ +Overview of changes leading to 1.5.1 +Tuesday, September 5, 2017 +==================================== + +- Fix "unsafe-to-break" in fallback shaping and other corner cases. + All our tests pass with --verify now, meaning unsafe-to-break API + works as expected. +- Add --unicodes to hb-view / hb-shape. +- [indic] Treat Consonant_With_Stacker as consonant. This will need + further tweaking. +- hb_buffer_diff() tweaks. + + Overview of changes leading to 1.5.0 Wednesday, August 23, 2017 ==================================== diff --git a/configure.ac b/configure.ac index 82895eab9..9151abc05 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [1.5.0], + [1.5.1], [https://github.com/behdad/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) From 9355218f582a6c2425cadcb868204f81b17d5767 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 9 Sep 2017 11:21:07 -0700 Subject: [PATCH 0389/1326] [util] Add a few shorthand forms for commandline options -o, -O, -u, -v, -V --- util/options.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/util/options.cc b/util/options.cc index 1abafdaa7..3aa6834dd 100644 --- a/util/options.cc +++ b/util/options.cc @@ -555,7 +555,7 @@ text_options_t::add_options (option_parser_t *parser) { {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"}, {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name\n\n If no text is provided, standard input is used for input.\n", "filename"}, - {"unicodes", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"}, + {"unicodes", 'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"}, {"text-before", 0, 0, G_OPTION_ARG_STRING, &this->text_before, "Set text context before each line", "string"}, {"text-after", 0, 0, G_OPTION_ARG_STRING, &this->text_after, "Set text context after each line", "string"}, {NULL} @@ -584,8 +584,8 @@ output_options_t::add_options (option_parser_t *parser) GOptionEntry entries[] = { - {"output-file", 0, 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"}, - {"output-format", 0, 0, G_OPTION_ARG_STRING, &this->output_format, text, "format"}, + {"output-file", 'o', 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"}, + {"output-format", 'O', 0, G_OPTION_ARG_STRING, &this->output_format, text, "format"}, {NULL} }; parser->add_group (entries, @@ -836,7 +836,7 @@ format_options_t::add_options (option_parser_t *parser) {"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Prefix each line of output with its corresponding input text", NULL}, {"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Prefix each line of output with its corresponding input codepoint(s)", NULL}, {"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Prefix each line of output with its corresponding input line number", NULL}, - {"verbose", 0, G_OPTION_FLAG_NO_ARG, + {"verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, (gpointer) &parse_verbose, "Prefix each line of output with all of the above", NULL}, {"no-glyph-names", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_glyph_names, "Output glyph indices instead of names", NULL}, @@ -846,7 +846,7 @@ format_options_t::add_options (option_parser_t *parser) G_OPTION_ARG_NONE, &this->show_clusters, "Do not output cluster indices", NULL}, {"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Output glyph extents", NULL}, {"show-flags", 0, 0, G_OPTION_ARG_NONE, &this->show_flags, "Output glyph flags", NULL}, - {"trace", 0, 0, G_OPTION_ARG_NONE, &this->trace, "Output interim shaping results", NULL}, + {"trace", 'V', 0, G_OPTION_ARG_NONE, &this->trace, "Output interim shaping results", NULL}, {NULL} }; parser->add_group (entries, From 3ca69c8c32b8408dd9f8e6e866cd07e58c0d79b7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 14 Sep 2017 20:50:35 -0400 Subject: [PATCH 0390/1326] Use strtod_l() to correctly parse decimal numbers in French & other locales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test with, eg.: $ LC_ALL=fr_FR.utf-8 ./hb-view NotoSansArabic-VF.ttf بهداد --variations wght=1.2 --- configure.ac | 4 ++-- src/hb-common.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 9151abc05..d65cae8cd 100644 --- a/configure.ac +++ b/configure.ac @@ -69,8 +69,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) ]) # Functions and headers -AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty) -AC_CHECK_HEADERS(unistd.h sys/mman.h) +AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l) +AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h) # Compiler flags AC_CANONICAL_HOST diff --git a/src/hb-common.cc b/src/hb-common.cc index 0483816d3..8e8e55653 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -32,6 +32,9 @@ #include "hb-object-private.hh" #include +#ifdef HAVE_XLOCALE_H +#include +#endif /* hb_options_t */ @@ -246,8 +249,8 @@ struct hb_language_item_t { static hb_language_item_t *langs; #ifdef HB_USE_ATEXIT -static -void free_langs (void) +static void +free_langs (void) { while (langs) { hb_language_item_t *next = langs->next; @@ -694,6 +697,48 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv) return true; } +#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L) +#define USE_XLOCALE 1 +#endif + +#ifdef USE_XLOCALE + +static locale_t C_locale; + +#ifdef HB_USE_ATEXIT +static void +free_C_locale (void) +{ + if (C_locale) + freelocale (C_locale); +} +#endif + +static locale_t +get_C_locale (void) +{ +retry: + locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale); + + if (unlikely (!C)) + { + C = newlocale (LC_ALL_MASK, "C", NULL); + + if (!hb_atomic_ptr_cmpexch (&C_locale, NULL, C)) + { + freelocale (C_locale); + goto retry; + } + +#ifdef HB_USE_ATEXIT + atexit (free_C_locale); /* First person registers atexit() callback. */ +#endif + } + + return C; +} +#endif + static bool parse_float (const char **pp, const char *end, float *pv) { @@ -707,7 +752,11 @@ parse_float (const char **pp, const char *end, float *pv) float v; errno = 0; +#ifdef USE_XLOCALE + v = strtod_l (p, &pend, get_C_locale ()); +#else v = strtod (p, &pend); +#endif if (errno || p == pend) return false; From 66128d3cfb12705530141b5a4bd2706f0cbb9fc5 Mon Sep 17 00:00:00 2001 From: mhosken Date: Wed, 27 Sep 2017 01:29:45 +0700 Subject: [PATCH 0391/1326] Fix missing xscale in rtl graphite unpacking (#541) * Fix missing xscale in rtl graphite unpacking * Oops didn't need to mess with yscale --- src/hb-graphite2.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index 9e0761e63..bc247c60c 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -389,7 +389,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan, } else { - curradvx = gr_seg_advance_X(seg); + curradvx = gr_seg_advance_X(seg) * xscale; for (is = gr_seg_first_slot (seg); is; pPos++, info++, is = gr_slot_next_in_segment (is)) { if (info->cluster != currclus) From 933a81d74fee0d5856fc7b15b58a16e0e0168e48 Mon Sep 17 00:00:00 2001 From: ebraminio Date: Sun, 1 Oct 2017 19:35:24 +0330 Subject: [PATCH 0392/1326] Add release checklist (#529) --- RELEASING.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 RELEASING.md diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 000000000..34f64988f --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,96 @@ +HarfBuzz release walk-through checklist: + +1. Open gitk and review changes since last release. + * `git diff $(git describe | sed 's/-.*//').. src/*.h` prints all public API changes. + + Document them in NEWS, All API and API semantic changes should be clearly + marked as API additions, API changes, or API deletions. + If there's a backward-incompatible API change (including deletions for API used anywhere), + that's a release blocker. Do NOT release. Document deprecations. +2. Based on severity of changes, decide whether it's a minor or micro release number bump, +3. Make sure you have correct date and new version at the top of NEWS file, +4. Bump version in configure.ac line 3, +5. Do "make distcheck", if it passes, you get a tarball. + Otherwise, fix things and commit them separately before making release, +6. "make release-files". Enter your GPG password again. This creates a sha256 hash and signs it. +7. Now that you have a tarball built, commit NEWS and configure.ac changes. The commit message + is simply the release number. Eg. "1.4.7" +8. Tag the release and sign it: Eg. "git tag -s 1.4.7 -m 1.4.7". Enter your GPG password. +9. Build win32 bundle. + 1. Put contents of [this](https://drive.google.com/open?id=0B3_fQkxDZZXXbWltRGd5bjVrUDQ) on your `~/.local/i686-w64-mingw32` + 2. Run `./MING32 --with-uniscribe` script (available below) to config harfbuzz with mingw + 3. make + 4. `./UPDATE.sh` (available below) +10. Copy all artefacts to users.freedesktop.org and move them into `/srv/www.freedesktop.org/www/software/harfbuzz/release` + There should be four files. Eg.: + ``` +-rw-r--r-- 1 behdad eng 1592693 Jul 18 11:25 harfbuzz-1.4.7.tar.bz2 +-rw-r--r-- 1 behdad eng 89 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256 +-rw-r--r-- 1 behdad eng 339 Jul 18 11:34 harfbuzz-1.4.7.tar.bz2.sha256.asc +-rw-r--r-- 1 behdad eng 2895619 Jul 18 11:34 harfbuzz-1.4.7-win32.zip +``` +11. While doing that, quickly double-check the size of the .tar.bz2 and .zip files against their previous releases to make sure nothing bad happened. They should be in the ballpark, perhaps slightly larger. Sometimes they do shrink, that's not by itself a stopper. +12. Push the commit and tag out: "git push --follow-tags". Make sure it's pushed both to freedesktop repo and github. +13. Upload artefacts and NEWS entry on the github release. + + +## MING32 +```bash +#!/bin/bash + +target=i686-w64-mingw32 + +unset CC +unset CXX +unset CPP +unset LD +unset LDFLAGS +unset CFLAGS +unset CXXFLAGS +unset PKG_CONFIG_PATH + +# Removed -static from the following +export CFLAGS="-static-libgcc" +export CXXFLAGS="-static-libgcc -static-libstdc++" +export CPPFLAGS=-I$HOME/.local/$target/include +export LDFLAGS=-L$HOME/.local/$target/lib +export PKG_CONFIG_LIBDIR=$HOME/.local/$target/lib/pkgconfig +export PATH=$HOME/.local/$target/bin:$PATH + +../configure --build=`~/script/config.guess` --host=$target --prefix=/home/behdad/.local/$target "$@" +``` + +## UPDATE.sh +```bash +#!/bin/bash + +v=$1 + +if test "x$v" = x; then + echo "usage: UPDATE.sh micro-version" + exit 1 +fi + +dir_prefix=harfbuzz-1.4. +dir_suffix=-win32 +dir=$dir_prefix$v$dir_suffix +dir_old=$dir_prefix$((v-1))$dir_suffix +if test -d "$dir"; then + echo "New dir $dir exists; not overwriting" + exit 1 +fi +if ! test -d "$dir_old"; then + echo "Old dir $dir_old does NOT exist; aborting" + exit 1 +fi +set -ex +cp -a "$dir_old" "$dir.tmp" +rm -f "$dir.tmp"/GDX32.dll +rm -f "$dir.tmp"/usp10.dll +cp ../winbuild/src/.libs/libharfbuzz-0.dll{,.def} $dir.tmp/ +cp ../winbuild/util/.libs/hb-{shape,view}.exe $dir.tmp/ +i686-w64-mingw32-strip $dir.tmp/{hb-shape.exe,hb-view.exe,libharfbuzz-0.dll} +mv $dir.tmp $dir +zip -r $dir.zip $dir +echo Bundle $dir.zip ready +``` From db446cce4ef4cd1a4f1652e3aa3e5e5ed1881d39 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 1 Oct 2017 12:06:00 -0400 Subject: [PATCH 0393/1326] Add RELEASING.md to dist --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 1d8f2e7c7..1755b73b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,7 @@ EXTRA_DIST = \ harfbuzz.doap \ README.python \ BUILD.md \ + RELEASING.md \ CMakeLists.txt \ $(NULL) From 19e77e01bc13f44138e1d50533327d314dd0a018 Mon Sep 17 00:00:00 2001 From: jfkthame Date: Mon, 2 Oct 2017 13:08:49 +0100 Subject: [PATCH 0394/1326] [shape-plan] Don't look for a cached plan if variation coords are specified. Fixes #549. (#550) This is a temporary hack just to avoid incorrect shaping results, pending proper support for caching shape-plans with variation coordinates. --- src/hb-shape-plan.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 3abf555c5..5573cd224 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -520,15 +520,17 @@ hb_shape_plan_create_cached2 (hb_face_t *face, retry: hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans); - for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) - if (hb_shape_plan_matches (node->shape_plan, &proposal)) - { - DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); - return hb_shape_plan_reference (node->shape_plan); - } + + /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */ + if (!hb_coords_present (coords, num_coords)) + for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) + if (hb_shape_plan_matches (node->shape_plan, &proposal)) + { + DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); + return hb_shape_plan_reference (node->shape_plan); + } /* Not found. */ - hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, user_features, num_user_features, coords, num_coords, From 1a0a356a0f2b2932581e4fd0437c01c058f4f6d1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 08:49:23 -0400 Subject: [PATCH 0395/1326] [indic] Categorize U+0980 BENGALI ANJI as placeholder Fixes https://github.com/behdad/harfbuzz/issues/538 --- src/hb-ot-shape-complex-indic.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 3cd8fd6c3..5acaadb5b 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -209,6 +209,7 @@ set_indic_properties (hb_glyph_info_t &info) pos = POS_ABOVE_C; } + else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/behdad/harfbuzz/issues/538 */ else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER; From da4866f7177a4e2836cc70b844e2e64ab671761f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 08:57:06 -0400 Subject: [PATCH 0396/1326] [arabic] Update table to Unicode 10 data --- src/hb-ot-shape-complex-arabic-table.hh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-shape-complex-arabic-table.hh b/src/hb-ot-shape-complex-arabic-table.hh index 228f36659..cd6e4058b 100644 --- a/src/hb-ot-shape-complex-arabic-table.hh +++ b/src/hb-ot-shape-complex-arabic-table.hh @@ -6,10 +6,10 @@ * * on files with these headers: * - * # ArabicShaping-9.0.0.txt - * # Date: 2016-02-24, 22:25:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # ArabicShaping-10.0.0.txt + * # Date: 2017-02-16, 00:00:00 GMT [RP, KW] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -72,7 +72,10 @@ static const uint8_t joining_table[] = /* Mandaic */ /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X, - /* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + + /* Syriac Supplement */ + + /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* Arabic Extended-A */ @@ -130,7 +133,7 @@ static const uint8_t joining_table[] = /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 1E940 */ D,D,D,D, -}; /* Table items: 1214; occupancy: 54% */ +}; /* Table items: 1214; occupancy: 55% */ static unsigned int From 819cc360499a5f136325b5a1a18098ebc2aee081 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 09:03:16 -0400 Subject: [PATCH 0397/1326] [indic] Move manual code out of generated table --- src/hb-ot-shape-complex-indic-table.cc | 7 ------- src/hb-ot-shape-complex-indic.cc | 5 +++++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc index 3bf5285e6..f0f4dc3be 100644 --- a/src/hb-ot-shape-complex-indic-table.cc +++ b/src/hb-ot-shape-complex-indic-table.cc @@ -422,13 +422,6 @@ hb_indic_get_categories (hb_codepoint_t u) if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u]; break; - case 0x11u: - // According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, - // so the Indic shaper needs to know their categories. - if (unlikely (u == 0x11303)) return _(Vs,R); - if (unlikely (u == 0x1133c)) return _(N,B); - break; - default: break; } diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 5acaadb5b..c8640cc56 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -209,6 +209,11 @@ set_indic_properties (hb_glyph_info_t &info) pos = POS_ABOVE_C; } + /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, + * so the Indic shaper needs to know their categories. */ + else if (unlikely (u == 0x11303u)) cat = OT_SM; + else if (unlikely (u == 0x1133cu)) cat = OT_N; + else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/behdad/harfbuzz/issues/538 */ else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) From cc79b666bc4a81a0342ed1e706dd7db109739dc5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 09:19:15 -0400 Subject: [PATCH 0398/1326] [indic] Add test for 1a0a356a0f2b2932581e4fd0437c01c058f4f6d1 https://github.com/behdad/harfbuzz/issues/538 --- .../87f85d17d26f1fe9ad28d7365101958edaefb967.ttf | Bin 0 -> 1000 bytes test/shaping/tests/indic-syllable.tests | 1 + 2 files changed, 1 insertion(+) create mode 100644 test/shaping/fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf diff --git a/test/shaping/fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf b/test/shaping/fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf new file mode 100644 index 0000000000000000000000000000000000000000..89b62575383a2e9b52351c12e510524dc0b027c3 GIT binary patch literal 1000 zcmZvbO-vI(6oB8%{&W|%+tQX@NTIC!w1`1NDXm0I1&bJCph`5x5MldcTSH5Q5+O0B zXuNnZ9!xxV@oqfm$pj8^Lk}hzE_(1_@TB2Dzz`3uZ(77ioXyPa_uiZLGjA6N0H{y| z4yHyT!)L$&JOK9$r41v|v2kbw1^G3yePsO7(A)PP@C3JpY>bT`^G{y8`U`*-kf-8V zGY^Wqj*JrmDRV9l7JPtvjI5-l7q83f+b{6_2hQDe(oF1J==*~97z2W76o{wDE95A0 zdpcWK5IV~bkR!;-^i14@DBMQI96`#O3wh9p0YEm8jhvZH@^iG=4a*#_t)>- zLuUR4fk2>KCZA{{^Z+<4qOR#$C>RR*ycW?S`n*0bBVB7IsL-`AL5+=wZQhe4fHt>U zjULaTW_OF->U7px?W)z~GPH(hm(fM6vR$!xb&=P6JkR$Y9irCD(f)QxvZ`)}Vs+M8 zL{4bv2n~qb;Xr)DXID7NNrJA45>f15Zw{Tnl4xm*hQUuau_JEGy4C9oc}TB67}8bJ z*4OIo3j}-pTD?nb%Y`R|PD`Y_J7Vb+Cc<@kqr;}@bu>KMFB}OS?-Ke)Gfvf})vIbf z){V~KC3Z54-DUK5&^>1N$~3eH-&fDMCv5{e(85)0R~NrMX9qrZJiJ?SmzMb$-9?mu zGAX(?AVDPv0F<_v54u}ghBf{Q+CJrD2ja0zc=DM%0s$>oD0Uatsyo>RKd`T8N z<=>GXHv8vJO7Ae{{|077 zDB&bCcOw%^=2Et}nM=%?u}m&8&$xPqvfITRtJ$-^gAG;*laM`m4R%zmXsWsz%+v$4 N;zo_-QvQ7{{01@$n@#`# literal 0 HcmV?d00001 diff --git a/test/shaping/tests/indic-syllable.tests b/test/shaping/tests/indic-syllable.tests index ecaad906b..df3d7d825 100644 --- a/test/shaping/tests/indic-syllable.tests +++ b/test/shaping/tests/indic-syllable.tests @@ -1,3 +1,4 @@ fonts/sha1sum/54674a3111d209fb6be0ed31745314b7a8d2c244.ttf::U+0BA4,U+0BCD,U+00B3:[taprehalftamil=0+1509|uni00B3=2+674] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF1:[gid1=0+1129] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF2:[gid2=0+1539] +fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf::U+0980,U+0981:[anjibeng=0+520|candrabindubeng=0+0] From bdbe974f525d33b8c735fb5d7fd76c236c4dd0ea Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 10:00:31 -0400 Subject: [PATCH 0399/1326] [indic] Update table to Unicode 10 --- src/hb-ot-shape-complex-indic-table.cc | 70 +++++++++++++------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc index f0f4dc3be..bfd1c6d34 100644 --- a/src/hb-ot-shape-complex-indic-table.cc +++ b/src/hb-ot-shape-complex-indic-table.cc @@ -6,61 +6,62 @@ * * on files with these headers: * - * # IndicSyllabicCategory-9.0.0.txt - * # Date: 2016-05-21, 02:46:00 GMT [RP] - * # IndicPositionalCategory-9.0.0.txt - * # Date: 2016-02-25, 00:48:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # IndicSyllabicCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [KW, RP] + * # IndicPositionalCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [RP] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] */ #include "hb-ot-shape-complex-indic-private.hh" #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 15 chars; Avagraha */ -#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 67 chars; Bindu */ +#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 80 chars; Bindu */ #define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */ -#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 53 chars; Cantillation_Mark */ -#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1907 chars; Consonant */ +#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 57 chars; Cantillation_Mark */ +#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2024 chars; Consonant */ #define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 10 chars; Consonant_Dead */ -#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */ +#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 68 chars; Consonant_Final */ #define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */ #define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */ -#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */ -#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 16 chars; Consonant_Placeholder */ -#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */ -#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */ -#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 90 chars; Consonant_Subjoined */ -#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */ +#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 27 chars; Consonant_Medial */ +#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 18 chars; Consonant_Placeholder */ +#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 2 chars; Consonant_Preceding_Repha */ +#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 7 chars; Consonant_Prefixed */ +#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 95 chars; Consonant_Subjoined */ +#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 5 chars; Consonant_Succeeding_Repha */ #define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */ -#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */ -#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */ +#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */ +#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 10 chars; Invisible_Stacker */ #define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */ #define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */ #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */ -#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 24 chars; Nukta */ -#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 459 chars; Number */ +#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 28 chars; Nukta */ +#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 469 chars; Number */ #define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */ #define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */ -#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */ +#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 21 chars; Pure_Killer */ #define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */ #define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 22 chars; Syllable_Modifier */ #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ #define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */ #define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 24 chars; Virama */ -#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 31 chars; Visarga */ +#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 34 chars; Visarga */ #define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */ -#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 602 chars; Vowel_Dependent */ -#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 431 chars; Vowel_Independent */ +#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 633 chars; Vowel_Dependent */ +#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 443 chars; Vowel_Independent */ -#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 300 chars; Bottom */ +#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 330 chars; Bottom */ +#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */ #define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */ #define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */ #define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */ #define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */ #define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */ -#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 258 chars; Right */ -#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 342 chars; Top */ +#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 262 chars; Right */ +#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 380 chars; Top */ #define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */ #define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */ #define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */ @@ -133,7 +134,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(x,x), _(x,x), /* Gurmukhi */ @@ -171,7 +172,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0AF8 */ _(x,x), _(C,x), _(Ca,T), _(Ca,T), _(Ca,T), _(N,T), _(N,T), _(N,T), /* Oriya */ @@ -251,14 +252,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Malayalam */ - /* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R), + /* 0D38 */ _(C,x), _(C,x), _(C,x), _(PK,T), _(PK,T), _(A,x), _(M,R), _(M,R), /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L), /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x), /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R), @@ -341,7 +342,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B), /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x), - /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x), + /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(Ca,R), /* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), #define indic_offset_0x2008u 1656 @@ -368,7 +369,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), - /* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x), #define indic_offset_0xa9e0u 1720 @@ -390,7 +391,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x), -}; /* Table items: 1784; occupancy: 69% */ +}; /* Table items: 1784; occupancy: 70% */ INDIC_TABLE_ELEMENT_TYPE hb_indic_get_categories (hb_codepoint_t u) @@ -467,6 +468,7 @@ hb_indic_get_categories (hb_codepoint_t u) #undef ISC_VI #undef IMC_B +#undef IMC_BL #undef IMC_BR #undef IMC_L #undef IMC_LR From 1535f8c67216e8559fa48691fe6d9c2726c08973 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 16:12:18 +0200 Subject: [PATCH 0400/1326] Add Unicode 10 scripts --- src/hb-common.h | 8 ++++++++ src/hb-ot-shape-complex-private.hh | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/hb-common.h b/src/hb-common.h index 634cb96a6..8614ee3fe 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -321,6 +321,14 @@ typedef enum /*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), + /* + * Since 1.6.0 + */ + /*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), + /*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), + /*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), + /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index 952441b6a..20ad6b2c7 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -362,6 +362,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MARCHEN: case HB_SCRIPT_NEWA: + /* Unicode-10.0 additions */ + case HB_SCRIPT_MASARAM_GONDI: + case HB_SCRIPT_SOYOMBO: + case HB_SCRIPT_ZANABAZAR_SQUARE: + /* If the designer designed the font for the 'DFLT' script, * use the default shaper. Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* From 29c244aff6e3c359796bb033496c14ad5537dbe0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 16:36:21 +0200 Subject: [PATCH 0401/1326] Minor --- src/gen-use-table.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gen-use-table.py b/src/gen-use-table.py index fcb66a580..2b36495c2 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -298,8 +298,7 @@ def map_to_use(data): # the nasalization marks, maybe only for U+1CE9..U+1CF1. if U == 0x1CED: UISC = Tone_Mark - evals = [(k, v(U,UISC,UGC)) for k,v in items] - values = [k for k,v in evals if v] + values = [k for k,v in items if v(U,UISC,UGC)] assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values) USE = values[0] From ea535a1dfa63f82280607273cd282a6134c334da Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 17:02:39 +0200 Subject: [PATCH 0402/1326] [use] Update to Unicode 10 --- src/gen-use-table.py | 5 +- src/hb-ot-shape-complex-use-table.cc | 69 ++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/gen-use-table.py b/src/gen-use-table.py index 2b36495c2..b283c5219 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -117,6 +117,7 @@ property_names = [ 'Top_And_Right', 'Top_And_Left', 'Top_And_Left_And_Right', + 'Bottom_And_Left', 'Bottom_And_Right', 'Top_And_Bottom_And_Right', 'Overstruck', @@ -153,7 +154,7 @@ def is_BASE(U, UISC, UGC): def is_BASE_IND(U, UISC, UGC): #SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po) return (UISC in [Consonant_Dead, Modifying_Letter] or - (UGC == Po and not U in [0x104E, 0x2022]) or + (UGC == Po and not U in [0x104E, 0x2022, 0x11A3F, 0x11A45]) or False # SPEC-DRAFT-OUTDATED! U == 0x002D ) def is_BASE_NUM(U, UISC, UGC): @@ -252,7 +253,7 @@ use_positions = { }, 'M': { 'Abv': [Top], - 'Blw': [Bottom], + 'Blw': [Bottom, Bottom_And_Left], 'Pst': [Right], 'Pre': [Left], }, diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index 941a003aa..f924ac05b 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -6,12 +6,12 @@ * * on files with these headers: * - * # IndicSyllabicCategory-9.0.0.txt - * # Date: 2016-05-21, 02:46:00 GMT [RP] - * # IndicPositionalCategory-9.0.0.txt - * # Date: 2016-06-09, 19:33:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # IndicSyllabicCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [KW, RP] + * # IndicPositionalCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [RP] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -97,7 +97,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O, /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, O, O, /* Gurmukhi */ @@ -119,7 +119,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O, /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O, + /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv, /* Oriya */ @@ -167,10 +167,10 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Malayalam */ - /* 0D00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, + /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst, + /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst, /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, /* 0D50 */ O, O, O, O, IND, IND, IND, VPst, O, O, O, O, O, O, O, B, /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, @@ -274,9 +274,9 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A50 */ B, B, B, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O, + /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, FAbv, SUB, SUB, SUB, SUB, O, /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM, + /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FM, FM, O, O, FM, /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -323,7 +323,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw, /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, - /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O, + /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, VMPst, VMAbv, VMAbv, O, O, O, O, O, O, #define use_offset_0x1df8u 2552 @@ -376,7 +376,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Devanagari Extended */ /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, - /* A8F0 */ VMAbv, VMAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, O, O, /* Kayah Li */ @@ -397,7 +397,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst, + /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MBlw, /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -545,7 +545,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst, /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, - /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, + /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B, /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, @@ -615,7 +615,26 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, -#define use_offset_0x11c00u 4960 +#define use_offset_0x11a00u 4960 + + + /* Zanabazar Square */ + + /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B, + /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A30 */ B, B, B, FM, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, + /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O, + + /* Soyombo */ + + /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B, + /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A80 */ B, B, B, B, O, O, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, + /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, O, O, O, + +#define use_offset_0x11c00u 5120 /* Bhaiksuki */ @@ -636,7 +655,19 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, -}; /* Table items: 5144; occupancy: 72% */ +#define use_offset_0x11d00u 5304 + + + /* Masaram Gondi */ + + /* 11D00 */ B, B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, + /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv, O, VAbv, + /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O, + /* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + +}; /* Table items: 5400; occupancy: 73% */ USE_TABLE_ELEMENT_TYPE hb_use_get_categories (hb_codepoint_t u) @@ -684,7 +715,9 @@ hb_use_get_categories (hb_codepoint_t u) if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; if (hb_in_range (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; + if (hb_in_range (u, 0x11A00u, 0x11A9Fu)) return use_table[u - 0x11A00u + use_offset_0x11a00u]; if (hb_in_range (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u]; + if (hb_in_range (u, 0x11D00u, 0x11D5Fu)) return use_table[u - 0x11D00u + use_offset_0x11d00u]; if (unlikely (u == 0x1107Fu)) return HN; break; From 0faa16a25349906ee0ab98b73d9a3d96327a0955 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 17:15:46 +0200 Subject: [PATCH 0403/1326] [ucdn] Update to Unicode 10 Update to commit c000ebf79c095a7d58cf90090bde5715592c4834 plus this bug-fix: https://github.com/grigorig/ucdn/issues/18 --- src/hb-ucdn.cc | 4 +++ src/hb-ucdn/Makefile.sources | 2 +- src/hb-ucdn/ucdn.c | 67 ++++++++++++++++++------------------ src/hb-ucdn/ucdn.h | 7 ++++ 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc index a884e3ffd..d8404b294 100644 --- a/src/hb-ucdn.cc +++ b/src/hb-ucdn.cc @@ -160,6 +160,10 @@ static const hb_script_t ucdn_script_translate[] = HB_SCRIPT_NEWA, HB_SCRIPT_OSAGE, HB_SCRIPT_TANGUT, + HB_SCRIPT_MASARAM_GONDI, + HB_SCRIPT_NUSHU, + HB_SCRIPT_SOYOMBO, + HB_SCRIPT_ZANABAZAR_SQUARE, }; static hb_unicode_combining_class_t diff --git a/src/hb-ucdn/Makefile.sources b/src/hb-ucdn/Makefile.sources index 52778d46c..cb823b605 100644 --- a/src/hb-ucdn/Makefile.sources +++ b/src/hb-ucdn/Makefile.sources @@ -3,5 +3,5 @@ NULL = LIBHB_UCDN_sources = \ ucdn.h \ ucdn.c \ - unicodedata_db.h \ + ucdn_db.h \ $(NULL) diff --git a/src/hb-ucdn/ucdn.c b/src/hb-ucdn/ucdn.c index f4e9be17c..30747fea2 100644 --- a/src/hb-ucdn/ucdn.c +++ b/src/hb-ucdn/ucdn.c @@ -23,7 +23,6 @@ typedef struct { unsigned char category; unsigned char combining; unsigned char bidi_class; - unsigned char mirrored; unsigned char east_asian_width; unsigned char script; unsigned char linebreak_class; @@ -43,7 +42,7 @@ typedef struct { short count, index; } Reindex; -#include "unicodedata_db.h" +#include "ucdn_db.h" /* constants required for Hangul (de)composition */ #define SBASE 0xAC00 @@ -91,20 +90,30 @@ static const unsigned short *get_decomp_record(uint32_t code) return &decomp_data[index]; } -static int get_comp_index(uint32_t code, const Reindex *idx) +static int compare_reindex(const void *a, const void *b) { - int i; + Reindex *ra = (Reindex *)a; + Reindex *rb = (Reindex *)b; - for (i = 0; idx[i].start; i++) { - const Reindex *cur = &idx[i]; - if (code < cur->start) - return -1; - if (code <= cur->start + cur->count) { - return cur->index + (code - cur->start); - } - } + if (ra->start < rb->start) + return -1; + else if (ra->start > (rb->start + rb->count)) + return 1; + else + return 0; +} - return -1; +static int get_comp_index(uint32_t code, const Reindex *idx, size_t len) +{ + Reindex *res; + Reindex r = {0, 0, 0}; + r.start = code; + res = (Reindex *) bsearch(&r, idx, len, sizeof(Reindex), compare_reindex); + + if (res != NULL) + return res->index + (code - res->start); + else + return -1; } static int compare_mp(const void *a, const void *b) @@ -127,8 +136,8 @@ static BracketPair *search_bp(uint32_t code) BracketPair *res; bp.from = code; - res = bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN, sizeof(BracketPair), - compare_bp); + res = (BracketPair *) bsearch(&bp, bracket_pairs, BIDI_BRACKET_LEN, + sizeof(BracketPair), compare_bp); return res; } @@ -154,23 +163,18 @@ static int hangul_pair_decompose(uint32_t code, uint32_t *a, uint32_t *b) static int hangul_pair_compose(uint32_t *code, uint32_t a, uint32_t b) { - if (b < VBASE || b >= (TBASE + TCOUNT)) - return 0; - - if ((a < LBASE || a >= (LBASE + LCOUNT)) - && (a < SBASE || a >= (SBASE + SCOUNT))) - return 0; - - if (a >= SBASE) { + if (a >= SBASE && a < (SBASE + SCOUNT) && b >= TBASE && b < (TBASE + TCOUNT)) { /* LV,T */ *code = a + (b - TBASE); return 3; - } else { + } else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT)) { /* L,V */ int li = a - LBASE; int vi = b - VBASE; *code = SBASE + li * NCOUNT + vi * TCOUNT; return 2; + } else { + return 0; } } @@ -178,7 +182,7 @@ static uint32_t decode_utf16(const unsigned short **code_ptr) { const unsigned short *code = *code_ptr; - if ((code[0] & 0xd800) != 0xd800) { + if (code[0] < 0xd800 || code[0] > 0xdc00) { *code_ptr += 1; return (uint32_t)code[0]; } else { @@ -215,7 +219,7 @@ int ucdn_get_bidi_class(uint32_t code) int ucdn_get_mirrored(uint32_t code) { - return get_ucd_record(code)->mirrored; + return ucdn_mirror(code) != code; } int ucdn_get_script(uint32_t code) @@ -264,12 +268,9 @@ uint32_t ucdn_mirror(uint32_t code) MirrorPair mp = {0}; MirrorPair *res; - if (get_ucd_record(code)->mirrored == 0) - return code; - mp.from = code; - res = bsearch(&mp, mirror_pairs, BIDI_MIRROR_LEN, sizeof(MirrorPair), - compare_mp); + res = (MirrorPair *) bsearch(&mp, mirror_pairs, BIDI_MIRROR_LEN, + sizeof(MirrorPair), compare_mp); if (res == NULL) return code; @@ -326,8 +327,8 @@ int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b) if (hangul_pair_compose(code, a, b)) return 1; - l = get_comp_index(a, nfc_first); - r = get_comp_index(b, nfc_last); + l = get_comp_index(a, nfc_first, sizeof(nfc_first) / sizeof(Reindex)); + r = get_comp_index(b, nfc_last, sizeof(nfc_last) / sizeof(Reindex)); if (l < 0 || r < 0) return 0; diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h index f694dc5a8..71a1e4b30 100644 --- a/src/hb-ucdn/ucdn.h +++ b/src/hb-ucdn/ucdn.h @@ -206,6 +206,10 @@ typedef unsigned __int64 uint64_t; #define UCDN_SCRIPT_NEWA 135 #define UCDN_SCRIPT_OSAGE 136 #define UCDN_SCRIPT_TANGUT 137 +#define UCDN_SCRIPT_MASARAM_GONDI 138 +#define UCDN_SCRIPT_NUSHU 139 +#define UCDN_SCRIPT_SOYOMBO 140 +#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141 #define UCDN_LINEBREAK_CLASS_OP 0 #define UCDN_LINEBREAK_CLASS_CL 1 @@ -247,6 +251,9 @@ typedef unsigned __int64 uint64_t; #define UCDN_LINEBREAK_CLASS_SG 37 #define UCDN_LINEBREAK_CLASS_SP 38 #define UCDN_LINEBREAK_CLASS_XX 39 +#define UCDN_LINEBREAK_CLASS_ZWJ 40 +#define UCDN_LINEBREAK_CLASS_EB 41 +#define UCDN_LINEBREAK_CLASS_EM 42 #define UCDN_GENERAL_CATEGORY_CC 0 #define UCDN_GENERAL_CATEGORY_CF 1 From 5680ef884cf31ab9b42c587ffa260e390c88b8eb Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:20:51 +0200 Subject: [PATCH 0404/1326] [use] Hack to fix shaping of U+1A7F Fixes https://github.com/behdad/harfbuzz/issues/525 --- src/gen-use-table.py | 3 +++ src/hb-ot-shape-complex-use-table.cc | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gen-use-table.py b/src/gen-use-table.py index b283c5219..4f4826125 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -299,6 +299,9 @@ def map_to_use(data): # the nasalization marks, maybe only for U+1CE9..U+1CF1. if U == 0x1CED: UISC = Tone_Mark + # TODO: https://github.com/behdad/harfbuzz/issues/525 + if U == 0x1A7F: UISC = Consonant_Final; UIPC = Bottom + values = [k for k,v in items if v(U,UISC,UGC)] assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values) USE = values[0] diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index f924ac05b..daae04ed3 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -276,7 +276,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, FAbv, SUB, SUB, SUB, SUB, O, /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FM, FM, O, O, FM, + /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FM, FM, O, O, FBlw, /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, From 57c55ef8341c760145170dedd002c5afb380e6c8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:21:27 +0200 Subject: [PATCH 0405/1326] [ot] Improve shaper selection heuristic --- src/hb-ot-shape-complex-private.hh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index 20ad6b2c7..8fadd7cdb 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -253,10 +253,12 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_SINHALA: /* If the designer designed the font for the 'DFLT' script, - * use the default shaper. Otherwise, use the specific shaper. + * (or we ended up arbitrarily pick 'latn'), use the default shaper. + * Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* * GSUB/GPOS needed, so there may be no scripts found! */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || + planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) return &_hb_ot_complex_shaper_default; else return &_hb_ot_complex_shaper_indic; @@ -368,10 +370,12 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_ZANABAZAR_SQUARE: /* If the designer designed the font for the 'DFLT' script, - * use the default shaper. Otherwise, use the specific shaper. + * (or we ended up arbitrarily pick 'latn'), use the default shaper. + * Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* * GSUB/GPOS needed, so there may be no scripts found! */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || + planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) return &_hb_ot_complex_shaper_default; else return &_hb_ot_complex_shaper_use; From b3dff7720c1fac8ca9bdd7087ac368a0af4349e8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:22:51 +0200 Subject: [PATCH 0406/1326] [ucdn] Update README --- src/hb-ucdn/README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-ucdn/README b/src/hb-ucdn/README index fcb97b9aa..2203ae69a 100644 --- a/src/hb-ucdn/README +++ b/src/hb-ucdn/README @@ -31,10 +31,10 @@ UCDN was written by Grigori Goronzy . How to Use -Include ucdn.c, ucdn.h and unicodedata_db.h in your project. Now, -just use the functions as documented in ucdn.h. +Include ucdn.c, ucdn.h and ucdn_db.h in your project. Now, just use the +functions as documented in ucdn.h. In some cases, it might be necessary to regenerate the Unicode database file. The script makeunicodedata.py (Python 3.x required) fetches the appropriate files and dumps the compressed database into -unicodedata_db.h. +ucdn_db.h. From cbec0cd65e1787b20ea55dd5583a7444938bd381 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:26:52 +0200 Subject: [PATCH 0407/1326] Remove some really old cruft --- src/hb-common.h | 14 -------------- src/hb-ucdn/ucdn.h | 14 -------------- 2 files changed, 28 deletions(-) diff --git a/src/hb-common.h b/src/hb-common.h index 8614ee3fe..614a63aa6 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -43,30 +43,16 @@ # endif /* !__cplusplus */ #endif -#if !defined (HB_DONT_DEFINE_STDINT) - #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ defined (_sgi) || defined (__sun) || defined (sun) || \ defined (__digital__) || defined (__HP_cc) # include #elif defined (_AIX) # include -/* VS 2010 (_MSC_VER 1600) has stdint.h */ -#elif defined (_MSC_VER) && _MSC_VER < 1600 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; #else # include #endif -#endif - HB_BEGIN_DECLS diff --git a/src/hb-ucdn/ucdn.h b/src/hb-ucdn/ucdn.h index 71a1e4b30..2d5fc3591 100644 --- a/src/hb-ucdn/ucdn.h +++ b/src/hb-ucdn/ucdn.h @@ -36,30 +36,16 @@ HB_BEGIN_HEADER -#if !defined (HB_DONT_DEFINE_STDINT) - #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ defined (_sgi) || defined (__sun) || defined (sun) || \ defined (__digital__) || defined (__HP_cc) # include #elif defined (_AIX) # include -/* VS 2010 (_MSC_VER 1600) has stdint.h */ -#elif defined (_MSC_VER) && _MSC_VER < 1600 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; #else # include #endif -#endif - #define UCDN_EAST_ASIAN_F 0 #define UCDN_EAST_ASIAN_H 1 From 6eb8950e6265b23d88ba35daab1cff4fc3fe8753 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:30:05 +0200 Subject: [PATCH 0408/1326] [ucdn] Oops! --- src/hb-ucdn/{unicodedata_db.h => ucdn_db.h} | 4320 ++++++++++--------- 1 file changed, 2173 insertions(+), 2147 deletions(-) rename src/hb-ucdn/{unicodedata_db.h => ucdn_db.h} (64%) diff --git a/src/hb-ucdn/unicodedata_db.h b/src/hb-ucdn/ucdn_db.h similarity index 64% rename from src/hb-ucdn/unicodedata_db.h rename to src/hb-ucdn/ucdn_db.h index c9cd59bc6..8d2d8de37 100644 --- a/src/hb-ucdn/unicodedata_db.h +++ b/src/hb-ucdn/ucdn_db.h @@ -1,999 +1,1012 @@ /* this file was generated by makeunicodedata.py 3.2 */ -#define UNIDATA_VERSION "9.0.0" +#define UNIDATA_VERSION "10.0.0" /* a list of unique database records */ static const UCDRecord ucd_records[] = { - {2, 0, 18, 0, 5, 102, 41}, - {0, 0, 14, 0, 5, 0, 21}, - {0, 0, 16, 0, 5, 0, 17}, - {0, 0, 15, 0, 5, 0, 35}, - {0, 0, 16, 0, 5, 0, 30}, - {0, 0, 17, 0, 5, 0, 30}, - {0, 0, 15, 0, 5, 0, 33}, - {0, 0, 15, 0, 5, 0, 21}, - {0, 0, 16, 0, 5, 0, 21}, - {29, 0, 17, 0, 3, 0, 40}, - {21, 0, 18, 0, 3, 0, 6}, - {21, 0, 18, 0, 3, 0, 3}, - {21, 0, 10, 0, 3, 0, 12}, - {23, 0, 10, 0, 3, 0, 9}, - {21, 0, 10, 0, 3, 0, 10}, - {21, 0, 18, 0, 3, 0, 12}, - {22, 0, 18, 1, 3, 0, 0}, - {18, 0, 18, 1, 3, 0, 2}, - {25, 0, 9, 0, 3, 0, 9}, - {21, 0, 12, 0, 3, 0, 8}, - {17, 0, 9, 0, 3, 0, 16}, - {21, 0, 12, 0, 3, 0, 7}, - {13, 0, 8, 0, 3, 0, 11}, - {21, 0, 18, 0, 3, 0, 8}, - {25, 0, 18, 1, 3, 0, 12}, - {25, 0, 18, 0, 3, 0, 12}, - {9, 0, 0, 0, 3, 1, 12}, - {21, 0, 18, 0, 3, 0, 9}, - {24, 0, 18, 0, 3, 0, 12}, - {16, 0, 18, 0, 3, 0, 12}, - {5, 0, 0, 0, 3, 1, 12}, - {25, 0, 18, 0, 3, 0, 17}, - {18, 0, 18, 1, 3, 0, 1}, - {0, 0, 15, 0, 5, 0, 36}, - {29, 0, 12, 0, 5, 0, 4}, - {21, 0, 18, 0, 4, 0, 0}, - {23, 0, 10, 0, 3, 0, 10}, - {23, 0, 10, 0, 4, 0, 9}, - {26, 0, 18, 0, 3, 0, 12}, - {21, 0, 18, 0, 4, 0, 29}, - {24, 0, 18, 0, 4, 0, 29}, - {26, 0, 18, 0, 5, 0, 12}, - {7, 0, 0, 0, 4, 1, 29}, - {20, 0, 18, 1, 5, 0, 3}, - {1, 0, 14, 0, 4, 0, 17}, - {26, 0, 18, 0, 4, 0, 12}, - {26, 0, 10, 0, 4, 0, 10}, - {25, 0, 10, 0, 4, 0, 9}, - {15, 0, 8, 0, 4, 0, 29}, - {24, 0, 18, 0, 4, 0, 18}, - {5, 0, 0, 0, 5, 0, 12}, - {19, 0, 18, 1, 5, 0, 3}, - {15, 0, 18, 0, 4, 0, 29}, - {9, 0, 0, 0, 5, 1, 12}, - {9, 0, 0, 0, 4, 1, 12}, - {25, 0, 18, 0, 4, 0, 29}, - {5, 0, 0, 0, 4, 1, 12}, - {5, 0, 0, 0, 5, 1, 12}, - {7, 0, 0, 0, 5, 1, 12}, - {8, 0, 0, 0, 5, 1, 12}, - {6, 0, 0, 0, 5, 1, 12}, - {6, 0, 18, 0, 5, 0, 12}, - {6, 0, 0, 0, 5, 0, 12}, - {24, 0, 18, 0, 5, 0, 12}, - {24, 0, 18, 0, 4, 0, 12}, - {6, 0, 18, 0, 4, 0, 29}, - {6, 0, 18, 0, 5, 0, 18}, - {6, 0, 0, 0, 4, 0, 29}, - {24, 0, 18, 0, 5, 34, 12}, - {12, 230, 13, 0, 4, 40, 21}, - {12, 232, 13, 0, 4, 40, 21}, - {12, 220, 13, 0, 4, 40, 21}, - {12, 216, 13, 0, 4, 40, 21}, - {12, 202, 13, 0, 4, 40, 21}, - {12, 1, 13, 0, 4, 40, 21}, - {12, 240, 13, 0, 4, 40, 21}, - {12, 0, 13, 0, 4, 40, 4}, - {12, 233, 13, 0, 4, 40, 4}, - {12, 234, 13, 0, 4, 40, 4}, - {9, 0, 0, 0, 5, 2, 12}, - {5, 0, 0, 0, 5, 2, 12}, - {24, 0, 18, 0, 5, 2, 12}, - {2, 0, 18, 0, 5, 102, 41}, - {6, 0, 0, 0, 5, 2, 12}, - {21, 0, 18, 0, 5, 0, 8}, - {21, 0, 18, 0, 5, 0, 12}, - {9, 0, 0, 0, 4, 2, 12}, - {5, 0, 0, 0, 4, 2, 12}, - {9, 0, 0, 0, 5, 54, 12}, - {5, 0, 0, 0, 5, 54, 12}, - {25, 0, 18, 0, 5, 2, 12}, - {9, 0, 0, 0, 5, 3, 12}, - {9, 0, 0, 0, 4, 3, 12}, - {5, 0, 0, 0, 4, 3, 12}, - {5, 0, 0, 0, 5, 3, 12}, - {26, 0, 0, 0, 5, 3, 12}, - {12, 230, 13, 0, 5, 3, 21}, - {12, 230, 13, 0, 5, 40, 21}, - {11, 0, 13, 0, 5, 3, 21}, - {9, 0, 0, 0, 5, 4, 12}, - {6, 0, 0, 0, 5, 4, 12}, - {21, 0, 0, 0, 5, 4, 12}, - {5, 0, 0, 0, 5, 4, 12}, - {21, 0, 0, 0, 5, 0, 8}, - {17, 0, 18, 0, 5, 4, 17}, - {26, 0, 18, 0, 5, 4, 12}, - {23, 0, 10, 0, 5, 4, 9}, - {12, 220, 13, 0, 5, 5, 21}, - {12, 230, 13, 0, 5, 5, 21}, - {12, 222, 13, 0, 5, 5, 21}, - {12, 228, 13, 0, 5, 5, 21}, - {12, 10, 13, 0, 5, 5, 21}, - {12, 11, 13, 0, 5, 5, 21}, - {12, 12, 13, 0, 5, 5, 21}, - {12, 13, 13, 0, 5, 5, 21}, - {12, 14, 13, 0, 5, 5, 21}, - {12, 15, 13, 0, 5, 5, 21}, - {12, 16, 13, 0, 5, 5, 21}, - {12, 17, 13, 0, 5, 5, 21}, - {12, 18, 13, 0, 5, 5, 21}, - {12, 19, 13, 0, 5, 5, 21}, - {12, 20, 13, 0, 5, 5, 21}, - {12, 21, 13, 0, 5, 5, 21}, - {12, 22, 13, 0, 5, 5, 21}, - {17, 0, 3, 0, 5, 5, 17}, - {12, 23, 13, 0, 5, 5, 21}, - {21, 0, 3, 0, 5, 5, 12}, - {12, 24, 13, 0, 5, 5, 21}, - {12, 25, 13, 0, 5, 5, 21}, - {21, 0, 3, 0, 5, 5, 6}, - {7, 0, 3, 0, 5, 5, 13}, - {1, 0, 11, 0, 5, 6, 12}, - {1, 0, 11, 0, 5, 0, 12}, - {25, 0, 18, 0, 5, 6, 12}, - {25, 0, 4, 0, 5, 6, 12}, - {21, 0, 10, 0, 5, 6, 10}, - {23, 0, 4, 0, 5, 6, 10}, - {21, 0, 12, 0, 5, 0, 8}, - {21, 0, 4, 0, 5, 6, 8}, - {26, 0, 18, 0, 5, 6, 12}, - {12, 230, 13, 0, 5, 6, 21}, - {12, 30, 13, 0, 5, 6, 21}, - {12, 31, 13, 0, 5, 6, 21}, - {12, 32, 13, 0, 5, 6, 21}, - {21, 0, 4, 0, 5, 0, 6}, - {1, 0, 4, 0, 5, 0, 21}, - {21, 0, 4, 0, 5, 6, 6}, - {7, 0, 4, 0, 5, 6, 12}, - {6, 0, 4, 0, 5, 0, 12}, - {12, 27, 13, 0, 5, 40, 21}, - {12, 28, 13, 0, 5, 40, 21}, - {12, 29, 13, 0, 5, 40, 21}, - {12, 30, 13, 0, 5, 40, 21}, - {12, 31, 13, 0, 5, 40, 21}, - {12, 32, 13, 0, 5, 40, 21}, - {12, 33, 13, 0, 5, 40, 21}, - {12, 34, 13, 0, 5, 40, 21}, - {12, 220, 13, 0, 5, 40, 21}, - {12, 220, 13, 0, 5, 6, 21}, - {13, 0, 11, 0, 5, 6, 11}, - {21, 0, 11, 0, 5, 6, 11}, - {21, 0, 4, 0, 5, 6, 12}, - {12, 35, 13, 0, 5, 40, 21}, - {6, 0, 4, 0, 5, 6, 12}, - {13, 0, 8, 0, 5, 6, 11}, - {26, 0, 4, 0, 5, 6, 12}, - {21, 0, 4, 0, 5, 7, 12}, - {1, 0, 4, 0, 5, 7, 12}, - {7, 0, 4, 0, 5, 7, 12}, - {12, 36, 13, 0, 5, 7, 21}, - {12, 230, 13, 0, 5, 7, 21}, - {12, 220, 13, 0, 5, 7, 21}, - {7, 0, 4, 0, 5, 8, 12}, - {12, 0, 13, 0, 5, 8, 21}, - {13, 0, 3, 0, 5, 65, 11}, - {7, 0, 3, 0, 5, 65, 12}, - {12, 230, 13, 0, 5, 65, 21}, - {12, 220, 13, 0, 5, 65, 21}, - {6, 0, 3, 0, 5, 65, 12}, - {26, 0, 18, 0, 5, 65, 12}, - {21, 0, 18, 0, 5, 65, 12}, - {21, 0, 18, 0, 5, 65, 8}, - {21, 0, 18, 0, 5, 65, 6}, - {7, 0, 3, 0, 5, 81, 12}, - {12, 230, 13, 0, 5, 81, 21}, - {6, 0, 3, 0, 5, 81, 12}, - {21, 0, 3, 0, 5, 81, 12}, - {7, 0, 3, 0, 5, 94, 12}, - {12, 220, 13, 0, 5, 94, 21}, - {21, 0, 3, 0, 5, 94, 12}, - {12, 27, 13, 0, 5, 6, 21}, - {12, 28, 13, 0, 5, 6, 21}, - {12, 29, 13, 0, 5, 6, 21}, - {12, 0, 13, 0, 5, 9, 21}, - {10, 0, 0, 0, 5, 9, 21}, - {7, 0, 0, 0, 5, 9, 12}, - {12, 7, 13, 0, 5, 9, 21}, - {12, 9, 13, 0, 5, 9, 21}, - {12, 230, 13, 0, 5, 9, 21}, - {21, 0, 0, 0, 5, 0, 17}, - {13, 0, 0, 0, 5, 9, 11}, - {21, 0, 0, 0, 5, 9, 12}, - {6, 0, 0, 0, 5, 9, 12}, - {7, 0, 0, 0, 5, 10, 12}, - {12, 0, 13, 0, 5, 10, 21}, - {10, 0, 0, 0, 5, 10, 21}, - {12, 7, 13, 0, 5, 10, 21}, - {12, 9, 13, 0, 5, 10, 21}, - {13, 0, 0, 0, 5, 10, 11}, - {23, 0, 10, 0, 5, 10, 10}, - {15, 0, 0, 0, 5, 10, 12}, - {15, 0, 0, 0, 5, 10, 10}, - {26, 0, 0, 0, 5, 10, 12}, - {23, 0, 10, 0, 5, 10, 9}, - {12, 0, 13, 0, 5, 11, 21}, - {10, 0, 0, 0, 5, 11, 21}, - {7, 0, 0, 0, 5, 11, 12}, - {12, 7, 13, 0, 5, 11, 21}, - {12, 9, 13, 0, 5, 11, 21}, - {13, 0, 0, 0, 5, 11, 11}, - {12, 0, 13, 0, 5, 12, 21}, - {10, 0, 0, 0, 5, 12, 21}, - {7, 0, 0, 0, 5, 12, 12}, - {12, 7, 13, 0, 5, 12, 21}, - {12, 9, 13, 0, 5, 12, 21}, - {13, 0, 0, 0, 5, 12, 11}, - {21, 0, 0, 0, 5, 12, 12}, - {23, 0, 10, 0, 5, 12, 9}, - {12, 0, 13, 0, 5, 13, 21}, - {10, 0, 0, 0, 5, 13, 21}, - {7, 0, 0, 0, 5, 13, 12}, - {12, 7, 13, 0, 5, 13, 21}, - {12, 9, 13, 0, 5, 13, 21}, - {13, 0, 0, 0, 5, 13, 11}, - {26, 0, 0, 0, 5, 13, 12}, - {15, 0, 0, 0, 5, 13, 12}, - {12, 0, 13, 0, 5, 14, 21}, - {7, 0, 0, 0, 5, 14, 12}, - {10, 0, 0, 0, 5, 14, 21}, - {12, 9, 13, 0, 5, 14, 21}, - {13, 0, 0, 0, 5, 14, 11}, - {15, 0, 0, 0, 5, 14, 12}, - {26, 0, 18, 0, 5, 14, 12}, - {23, 0, 10, 0, 5, 14, 9}, - {12, 0, 13, 0, 5, 15, 21}, - {10, 0, 0, 0, 5, 15, 21}, - {7, 0, 0, 0, 5, 15, 12}, - {12, 9, 13, 0, 5, 15, 21}, - {12, 84, 13, 0, 5, 15, 21}, - {12, 91, 13, 0, 5, 15, 21}, - {13, 0, 0, 0, 5, 15, 11}, - {15, 0, 18, 0, 5, 15, 12}, - {26, 0, 0, 0, 5, 15, 12}, - {7, 0, 0, 0, 5, 16, 12}, - {12, 0, 13, 0, 5, 16, 21}, - {10, 0, 0, 0, 5, 16, 21}, - {12, 7, 13, 0, 5, 16, 21}, - {12, 0, 0, 0, 5, 16, 21}, - {12, 9, 13, 0, 5, 16, 21}, - {13, 0, 0, 0, 5, 16, 11}, - {12, 0, 13, 0, 5, 17, 21}, - {10, 0, 0, 0, 5, 17, 21}, - {7, 0, 0, 0, 5, 17, 12}, - {12, 9, 13, 0, 5, 17, 21}, - {26, 0, 0, 0, 5, 17, 12}, - {15, 0, 0, 0, 5, 17, 12}, - {13, 0, 0, 0, 5, 17, 11}, - {26, 0, 0, 0, 5, 17, 10}, - {10, 0, 0, 0, 5, 18, 21}, - {7, 0, 0, 0, 5, 18, 12}, - {12, 9, 13, 0, 5, 18, 21}, - {12, 0, 13, 0, 5, 18, 21}, - {13, 0, 0, 0, 5, 18, 11}, - {21, 0, 0, 0, 5, 18, 12}, - {7, 0, 0, 0, 5, 19, 38}, - {12, 0, 13, 0, 5, 19, 38}, - {12, 103, 13, 0, 5, 19, 38}, - {12, 9, 13, 0, 5, 19, 38}, - {23, 0, 10, 0, 5, 0, 9}, - {6, 0, 0, 0, 5, 19, 38}, - {12, 107, 13, 0, 5, 19, 38}, - {21, 0, 0, 0, 5, 19, 12}, - {13, 0, 0, 0, 5, 19, 11}, - {21, 0, 0, 0, 5, 19, 17}, - {7, 0, 0, 0, 5, 20, 38}, - {12, 0, 13, 0, 5, 20, 38}, - {12, 118, 13, 0, 5, 20, 38}, - {6, 0, 0, 0, 5, 20, 38}, - {12, 122, 13, 0, 5, 20, 38}, - {13, 0, 0, 0, 5, 20, 11}, - {7, 0, 0, 0, 5, 21, 12}, - {26, 0, 0, 0, 5, 21, 18}, - {21, 0, 0, 0, 5, 21, 18}, - {21, 0, 0, 0, 5, 21, 12}, - {21, 0, 0, 0, 5, 21, 4}, - {21, 0, 0, 0, 5, 21, 17}, - {21, 0, 0, 0, 5, 21, 6}, - {26, 0, 0, 0, 5, 21, 12}, - {12, 220, 13, 0, 5, 21, 21}, - {13, 0, 0, 0, 5, 21, 11}, - {15, 0, 0, 0, 5, 21, 12}, - {26, 0, 0, 0, 5, 21, 17}, - {12, 216, 13, 0, 5, 21, 21}, - {22, 0, 18, 1, 5, 21, 0}, - {18, 0, 18, 1, 5, 21, 1}, - {10, 0, 0, 0, 5, 21, 21}, - {12, 129, 13, 0, 5, 21, 21}, - {12, 130, 13, 0, 5, 21, 21}, - {12, 0, 13, 0, 5, 21, 21}, - {12, 132, 13, 0, 5, 21, 21}, - {10, 0, 0, 0, 5, 21, 17}, - {12, 230, 13, 0, 5, 21, 21}, - {12, 9, 13, 0, 5, 21, 21}, - {26, 0, 0, 0, 5, 0, 12}, - {7, 0, 0, 0, 5, 22, 38}, - {10, 0, 0, 0, 5, 22, 38}, - {12, 0, 13, 0, 5, 22, 38}, - {12, 7, 13, 0, 5, 22, 38}, - {12, 9, 13, 0, 5, 22, 38}, - {13, 0, 0, 0, 5, 22, 11}, - {21, 0, 0, 0, 5, 22, 17}, - {21, 0, 0, 0, 5, 22, 12}, - {12, 220, 13, 0, 5, 22, 38}, - {26, 0, 0, 0, 5, 22, 38}, - {9, 0, 0, 0, 5, 23, 12}, - {7, 0, 0, 0, 5, 23, 12}, - {21, 0, 0, 0, 5, 0, 12}, - {6, 0, 0, 0, 5, 23, 12}, - {7, 0, 0, 0, 2, 24, 25}, - {7, 0, 0, 0, 5, 24, 26}, - {7, 0, 0, 0, 5, 24, 27}, - {7, 0, 0, 0, 5, 25, 12}, - {12, 230, 13, 0, 5, 25, 21}, - {21, 0, 0, 0, 5, 25, 12}, - {21, 0, 0, 0, 5, 25, 17}, - {15, 0, 0, 0, 5, 25, 12}, - {26, 0, 18, 0, 5, 25, 12}, - {9, 0, 0, 0, 5, 26, 12}, - {5, 0, 0, 0, 5, 26, 12}, - {17, 0, 18, 0, 5, 27, 17}, - {7, 0, 0, 0, 5, 27, 12}, - {21, 0, 0, 0, 5, 27, 12}, - {29, 0, 17, 0, 5, 28, 17}, - {7, 0, 0, 0, 5, 28, 12}, - {22, 0, 18, 1, 5, 28, 0}, - {18, 0, 18, 1, 5, 28, 1}, - {7, 0, 0, 0, 5, 29, 12}, - {14, 0, 0, 0, 5, 29, 12}, - {7, 0, 0, 0, 5, 41, 12}, - {12, 0, 13, 0, 5, 41, 21}, - {12, 9, 13, 0, 5, 41, 21}, - {7, 0, 0, 0, 5, 42, 12}, - {12, 0, 13, 0, 5, 42, 21}, - {12, 9, 13, 0, 5, 42, 21}, - {7, 0, 0, 0, 5, 43, 12}, - {12, 0, 13, 0, 5, 43, 21}, - {7, 0, 0, 0, 5, 44, 12}, - {12, 0, 13, 0, 5, 44, 21}, - {7, 0, 0, 0, 5, 30, 38}, - {12, 0, 13, 0, 5, 30, 38}, - {10, 0, 0, 0, 5, 30, 38}, - {12, 9, 13, 0, 5, 30, 38}, - {21, 0, 0, 0, 5, 30, 17}, - {21, 0, 0, 0, 5, 30, 5}, - {6, 0, 0, 0, 5, 30, 38}, - {21, 0, 0, 0, 5, 30, 12}, - {23, 0, 10, 0, 5, 30, 9}, - {12, 230, 13, 0, 5, 30, 38}, - {13, 0, 0, 0, 5, 30, 11}, - {15, 0, 18, 0, 5, 30, 12}, - {21, 0, 18, 0, 5, 31, 12}, - {21, 0, 18, 0, 5, 0, 6}, - {21, 0, 18, 0, 5, 31, 17}, - {21, 0, 18, 0, 5, 0, 17}, - {17, 0, 18, 0, 5, 31, 18}, - {21, 0, 18, 0, 5, 31, 6}, - {12, 0, 13, 0, 5, 31, 21}, - {1, 0, 14, 0, 5, 31, 4}, - {13, 0, 0, 0, 5, 31, 11}, - {7, 0, 0, 0, 5, 31, 12}, - {6, 0, 0, 0, 5, 31, 12}, - {12, 228, 13, 0, 5, 31, 21}, - {7, 0, 0, 0, 5, 45, 12}, - {12, 0, 13, 0, 5, 45, 21}, - {10, 0, 0, 0, 5, 45, 21}, - {12, 222, 13, 0, 5, 45, 21}, - {12, 230, 13, 0, 5, 45, 21}, - {12, 220, 13, 0, 5, 45, 21}, - {26, 0, 18, 0, 5, 45, 12}, - {21, 0, 18, 0, 5, 45, 6}, - {13, 0, 0, 0, 5, 45, 11}, - {7, 0, 0, 0, 5, 46, 38}, - {7, 0, 0, 0, 5, 55, 38}, - {13, 0, 0, 0, 5, 55, 11}, - {15, 0, 0, 0, 5, 55, 38}, - {26, 0, 18, 0, 5, 55, 38}, - {26, 0, 18, 0, 5, 30, 12}, - {7, 0, 0, 0, 5, 53, 12}, - {12, 230, 13, 0, 5, 53, 21}, - {12, 220, 13, 0, 5, 53, 21}, - {10, 0, 0, 0, 5, 53, 21}, - {12, 0, 13, 0, 5, 53, 21}, - {21, 0, 0, 0, 5, 53, 12}, - {7, 0, 0, 0, 5, 77, 38}, - {10, 0, 0, 0, 5, 77, 38}, - {12, 0, 13, 0, 5, 77, 38}, - {12, 9, 13, 0, 5, 77, 38}, - {12, 230, 13, 0, 5, 77, 38}, - {12, 220, 13, 0, 5, 77, 21}, - {13, 0, 0, 0, 5, 77, 11}, - {21, 0, 0, 0, 5, 77, 38}, - {6, 0, 0, 0, 5, 77, 38}, - {11, 0, 13, 0, 5, 40, 21}, - {12, 0, 13, 0, 5, 61, 21}, - {10, 0, 0, 0, 5, 61, 21}, - {7, 0, 0, 0, 5, 61, 12}, - {12, 7, 13, 0, 5, 61, 21}, - {10, 9, 0, 0, 5, 61, 21}, - {13, 0, 0, 0, 5, 61, 11}, - {21, 0, 0, 0, 5, 61, 17}, - {21, 0, 0, 0, 5, 61, 12}, - {26, 0, 0, 0, 5, 61, 12}, - {12, 230, 13, 0, 5, 61, 21}, - {12, 220, 13, 0, 5, 61, 21}, - {12, 0, 13, 0, 5, 66, 21}, - {10, 0, 0, 0, 5, 66, 21}, - {7, 0, 0, 0, 5, 66, 12}, - {10, 9, 0, 0, 5, 66, 21}, - {12, 9, 13, 0, 5, 66, 21}, - {13, 0, 0, 0, 5, 66, 11}, - {7, 0, 0, 0, 5, 92, 12}, - {12, 7, 13, 0, 5, 92, 21}, - {10, 0, 0, 0, 5, 92, 21}, - {12, 0, 13, 0, 5, 92, 21}, - {10, 9, 0, 0, 5, 92, 21}, - {21, 0, 0, 0, 5, 92, 12}, - {7, 0, 0, 0, 5, 67, 12}, - {10, 0, 0, 0, 5, 67, 21}, - {12, 0, 13, 0, 5, 67, 21}, - {12, 7, 13, 0, 5, 67, 21}, - {21, 0, 0, 0, 5, 67, 17}, - {13, 0, 0, 0, 5, 67, 11}, - {13, 0, 0, 0, 5, 68, 11}, - {7, 0, 0, 0, 5, 68, 12}, - {6, 0, 0, 0, 5, 68, 12}, - {21, 0, 0, 0, 5, 68, 17}, - {21, 0, 0, 0, 5, 66, 12}, - {12, 1, 13, 0, 5, 40, 21}, - {10, 0, 0, 0, 5, 0, 21}, - {7, 0, 0, 0, 5, 0, 12}, - {6, 0, 0, 0, 5, 3, 12}, - {12, 234, 13, 0, 5, 40, 21}, - {12, 214, 13, 0, 5, 40, 21}, - {12, 202, 13, 0, 5, 40, 21}, - {12, 233, 13, 0, 5, 40, 21}, - {8, 0, 0, 0, 5, 2, 12}, - {24, 0, 18, 0, 5, 2, 18}, - {29, 0, 17, 0, 5, 0, 17}, - {29, 0, 17, 0, 5, 0, 4}, - {1, 0, 14, 0, 5, 0, 20}, - {1, 0, 14, 0, 5, 40, 21}, - {1, 0, 14, 0, 5, 40, 41}, - {1, 0, 0, 0, 5, 0, 21}, - {1, 0, 3, 0, 5, 0, 21}, - {17, 0, 18, 0, 4, 0, 17}, - {17, 0, 18, 0, 5, 0, 4}, - {17, 0, 18, 0, 5, 0, 17}, - {17, 0, 18, 0, 4, 0, 19}, - {17, 0, 18, 0, 4, 0, 29}, - {20, 0, 18, 0, 4, 0, 3}, - {19, 0, 18, 0, 4, 0, 3}, - {22, 0, 18, 0, 5, 0, 0}, - {20, 0, 18, 0, 5, 0, 3}, - {21, 0, 18, 0, 4, 0, 12}, - {21, 0, 18, 0, 4, 0, 15}, - {21, 0, 18, 0, 4, 0, 17}, - {27, 0, 17, 0, 5, 0, 30}, - {28, 0, 15, 0, 5, 0, 30}, - {1, 0, 1, 0, 5, 0, 21}, - {1, 0, 5, 0, 5, 0, 21}, - {1, 0, 7, 0, 5, 0, 21}, - {1, 0, 2, 0, 5, 0, 21}, - {1, 0, 6, 0, 5, 0, 21}, - {21, 0, 10, 0, 4, 0, 10}, - {21, 0, 10, 0, 5, 0, 10}, - {21, 0, 18, 0, 4, 0, 10}, - {21, 0, 18, 0, 5, 0, 10}, - {21, 0, 18, 0, 5, 0, 5}, - {16, 0, 18, 0, 5, 0, 12}, - {25, 0, 12, 0, 5, 0, 8}, - {22, 0, 18, 1, 5, 0, 0}, - {18, 0, 18, 1, 5, 0, 1}, - {25, 0, 18, 0, 5, 0, 12}, - {1, 0, 14, 0, 5, 0, 22}, - {1, 0, 14, 0, 5, 0, 12}, - {1, 0, 19, 0, 5, 0, 21}, - {1, 0, 20, 0, 5, 0, 21}, - {1, 0, 21, 0, 5, 0, 21}, - {1, 0, 22, 0, 5, 0, 21}, - {1, 0, 14, 0, 5, 0, 21}, - {15, 0, 8, 0, 5, 0, 12}, - {25, 0, 9, 0, 5, 0, 12}, - {6, 0, 0, 0, 4, 1, 29}, - {23, 0, 10, 0, 5, 0, 10}, - {23, 0, 10, 0, 1, 0, 9}, - {2, 0, 18, 0, 5, 102, 9}, - {9, 0, 0, 0, 5, 0, 12}, - {26, 0, 18, 0, 4, 0, 10}, - {26, 0, 18, 0, 4, 0, 29}, - {5, 0, 0, 0, 4, 0, 29}, - {26, 0, 18, 0, 4, 0, 9}, - {9, 0, 0, 0, 4, 1, 29}, - {26, 0, 10, 0, 5, 0, 12}, - {25, 0, 18, 1, 5, 0, 12}, - {15, 0, 18, 0, 5, 0, 12}, - {15, 0, 18, 0, 4, 0, 12}, - {15, 0, 18, 0, 5, 0, 29}, - {14, 0, 0, 0, 4, 1, 29}, - {14, 0, 0, 0, 5, 1, 12}, - {25, 0, 18, 1, 4, 0, 29}, - {25, 0, 9, 0, 5, 0, 9}, - {25, 0, 10, 0, 5, 0, 9}, - {25, 0, 18, 0, 5, 0, 15}, - {26, 0, 18, 0, 2, 0, 14}, - {22, 0, 18, 1, 2, 0, 0}, - {18, 0, 18, 1, 2, 0, 1}, - {26, 0, 18, 0, 2, 0, 12}, - {26, 0, 18, 0, 5, 0, 14}, - {26, 0, 0, 0, 4, 0, 29}, - {26, 0, 18, 0, 5, 0, 29}, - {25, 0, 18, 0, 2, 0, 12}, - {26, 0, 18, 0, 4, 0, 14}, - {26, 0, 18, 0, 5, 0, 41}, - {26, 0, 18, 0, 4, 0, 41}, - {26, 0, 18, 0, 2, 0, 41}, - {26, 0, 18, 0, 2, 0, 29}, - {26, 0, 18, 0, 5, 0, 3}, - {26, 0, 18, 0, 5, 0, 6}, - {26, 0, 0, 0, 5, 52, 12}, - {9, 0, 0, 0, 5, 56, 12}, - {5, 0, 0, 0, 5, 56, 12}, - {26, 0, 18, 0, 5, 54, 12}, - {12, 230, 13, 0, 5, 54, 21}, - {21, 0, 18, 0, 5, 54, 6}, - {21, 0, 18, 0, 5, 54, 17}, - {15, 0, 18, 0, 5, 54, 12}, - {5, 0, 0, 0, 5, 23, 12}, - {7, 0, 0, 0, 5, 57, 12}, - {6, 0, 0, 0, 5, 57, 12}, - {21, 0, 0, 0, 5, 57, 17}, - {12, 9, 13, 0, 5, 57, 21}, - {21, 0, 18, 0, 5, 0, 3}, - {21, 0, 18, 0, 5, 0, 0}, - {17, 0, 18, 0, 5, 0, 12}, - {17, 0, 18, 0, 5, 0, 19}, - {26, 0, 18, 0, 2, 35, 14}, - {29, 0, 17, 0, 0, 0, 17}, - {21, 0, 18, 0, 2, 0, 1}, - {21, 0, 18, 0, 2, 0, 14}, - {6, 0, 0, 0, 2, 35, 5}, - {7, 0, 0, 0, 2, 0, 14}, - {14, 0, 0, 0, 2, 35, 14}, - {17, 0, 18, 0, 2, 0, 5}, - {22, 0, 18, 0, 2, 0, 0}, - {18, 0, 18, 0, 2, 0, 1}, - {12, 218, 13, 0, 2, 40, 21}, - {12, 228, 13, 0, 2, 40, 21}, - {12, 232, 13, 0, 2, 40, 21}, - {12, 222, 13, 0, 2, 40, 21}, - {10, 224, 0, 0, 2, 24, 21}, - {17, 0, 18, 0, 2, 0, 14}, - {6, 0, 0, 0, 2, 0, 14}, - {6, 0, 0, 0, 2, 0, 21}, - {7, 0, 0, 0, 2, 0, 5}, - {7, 0, 0, 0, 2, 32, 32}, - {7, 0, 0, 0, 2, 32, 14}, - {12, 8, 13, 0, 2, 40, 21}, - {24, 0, 18, 0, 2, 0, 5}, - {6, 0, 0, 0, 2, 32, 5}, - {7, 0, 0, 0, 2, 33, 32}, - {7, 0, 0, 0, 2, 33, 14}, - {21, 0, 18, 0, 2, 0, 5}, - {6, 0, 0, 0, 2, 0, 32}, - {6, 0, 0, 0, 2, 33, 5}, - {7, 0, 0, 0, 2, 34, 14}, - {7, 0, 0, 0, 2, 24, 14}, - {26, 0, 0, 0, 2, 0, 14}, - {15, 0, 0, 0, 2, 0, 14}, - {26, 0, 0, 0, 2, 24, 14}, - {26, 0, 18, 0, 2, 24, 14}, - {15, 0, 0, 0, 4, 0, 29}, - {15, 0, 18, 0, 2, 0, 14}, - {26, 0, 0, 0, 2, 33, 14}, - {7, 0, 0, 0, 2, 35, 14}, - {2, 0, 18, 0, 2, 102, 14}, - {7, 0, 0, 0, 2, 36, 14}, - {6, 0, 0, 0, 2, 36, 5}, - {26, 0, 18, 0, 2, 36, 14}, - {7, 0, 0, 0, 5, 82, 12}, - {6, 0, 0, 0, 5, 82, 12}, - {21, 0, 0, 0, 5, 82, 17}, - {7, 0, 0, 0, 5, 69, 12}, - {6, 0, 0, 0, 5, 69, 12}, - {21, 0, 18, 0, 5, 69, 17}, - {21, 0, 18, 0, 5, 69, 6}, - {13, 0, 0, 0, 5, 69, 11}, - {7, 0, 0, 0, 5, 3, 12}, - {21, 0, 18, 0, 5, 3, 12}, - {6, 0, 18, 0, 5, 3, 12}, - {7, 0, 0, 0, 5, 83, 12}, - {14, 0, 0, 0, 5, 83, 12}, - {12, 230, 13, 0, 5, 83, 21}, - {21, 0, 0, 0, 5, 83, 12}, - {21, 0, 0, 0, 5, 83, 17}, - {24, 0, 0, 0, 5, 0, 12}, - {7, 0, 0, 0, 5, 58, 12}, - {12, 0, 13, 0, 5, 58, 21}, - {12, 9, 13, 0, 5, 58, 21}, - {10, 0, 0, 0, 5, 58, 21}, - {26, 0, 18, 0, 5, 58, 12}, - {15, 0, 0, 0, 5, 0, 12}, - {7, 0, 0, 0, 5, 64, 12}, - {21, 0, 18, 0, 5, 64, 18}, - {21, 0, 18, 0, 5, 64, 6}, - {10, 0, 0, 0, 5, 70, 21}, - {7, 0, 0, 0, 5, 70, 12}, - {12, 9, 13, 0, 5, 70, 21}, - {12, 0, 13, 0, 5, 70, 21}, - {21, 0, 0, 0, 5, 70, 17}, - {13, 0, 0, 0, 5, 70, 11}, - {21, 0, 0, 0, 5, 9, 18}, - {13, 0, 0, 0, 5, 71, 11}, - {7, 0, 0, 0, 5, 71, 12}, - {12, 0, 13, 0, 5, 71, 21}, - {12, 220, 13, 0, 5, 71, 21}, - {21, 0, 0, 0, 5, 71, 17}, - {7, 0, 0, 0, 5, 72, 12}, - {12, 0, 13, 0, 5, 72, 21}, - {10, 0, 0, 0, 5, 72, 21}, - {10, 9, 0, 0, 5, 72, 21}, - {21, 0, 0, 0, 5, 72, 12}, - {12, 0, 13, 0, 5, 84, 21}, - {10, 0, 0, 0, 5, 84, 21}, - {7, 0, 0, 0, 5, 84, 12}, - {12, 7, 13, 0, 5, 84, 21}, - {10, 9, 0, 0, 5, 84, 21}, - {21, 0, 0, 0, 5, 84, 12}, - {21, 0, 0, 0, 5, 84, 17}, - {13, 0, 0, 0, 5, 84, 11}, - {6, 0, 0, 0, 5, 22, 38}, - {7, 0, 0, 0, 5, 76, 12}, - {12, 0, 13, 0, 5, 76, 21}, - {10, 0, 0, 0, 5, 76, 21}, - {13, 0, 0, 0, 5, 76, 11}, - {21, 0, 0, 0, 5, 76, 12}, - {21, 0, 0, 0, 5, 76, 17}, - {7, 0, 0, 0, 5, 78, 38}, - {12, 230, 13, 0, 5, 78, 38}, - {12, 220, 13, 0, 5, 78, 38}, - {6, 0, 0, 0, 5, 78, 38}, - {21, 0, 0, 0, 5, 78, 38}, - {7, 0, 0, 0, 5, 85, 12}, - {10, 0, 0, 0, 5, 85, 21}, - {12, 0, 13, 0, 5, 85, 21}, - {21, 0, 0, 0, 5, 85, 17}, - {6, 0, 0, 0, 5, 85, 12}, - {12, 9, 13, 0, 5, 85, 21}, - {13, 0, 0, 0, 5, 85, 11}, - {7, 0, 0, 0, 2, 24, 23}, - {7, 0, 0, 0, 2, 24, 24}, - {4, 0, 0, 0, 5, 102, 39}, - {3, 0, 0, 0, 4, 102, 41}, - {12, 26, 13, 0, 5, 5, 21}, - {25, 0, 9, 0, 5, 5, 12}, - {24, 0, 4, 0, 5, 6, 12}, - {18, 0, 18, 0, 5, 0, 1}, - {12, 0, 13, 0, 4, 40, 21}, - {21, 0, 18, 0, 2, 0, 8}, - {21, 0, 18, 0, 2, 0, 6}, - {21, 0, 18, 0, 2, 0, 15}, - {16, 0, 18, 0, 2, 0, 14}, - {21, 0, 12, 0, 2, 0, 1}, - {21, 0, 12, 0, 2, 0, 5}, - {21, 0, 10, 0, 2, 0, 14}, - {25, 0, 9, 0, 2, 0, 14}, - {17, 0, 9, 0, 2, 0, 14}, - {25, 0, 18, 1, 2, 0, 14}, - {25, 0, 18, 0, 2, 0, 14}, - {23, 0, 10, 0, 2, 0, 9}, - {21, 0, 10, 0, 2, 0, 10}, - {21, 0, 18, 0, 0, 0, 6}, - {21, 0, 18, 0, 0, 0, 14}, - {21, 0, 10, 0, 0, 0, 14}, - {23, 0, 10, 0, 0, 0, 9}, - {21, 0, 10, 0, 0, 0, 10}, - {22, 0, 18, 1, 0, 0, 0}, - {18, 0, 18, 1, 0, 0, 1}, - {25, 0, 9, 0, 0, 0, 14}, - {21, 0, 12, 0, 0, 0, 1}, - {17, 0, 9, 0, 0, 0, 14}, - {21, 0, 12, 0, 0, 0, 14}, - {13, 0, 8, 0, 0, 0, 14}, - {21, 0, 12, 0, 0, 0, 5}, - {21, 0, 18, 0, 0, 0, 5}, - {25, 0, 18, 1, 0, 0, 14}, - {25, 0, 18, 0, 0, 0, 14}, - {9, 0, 0, 0, 0, 1, 14}, - {24, 0, 18, 0, 0, 0, 14}, - {16, 0, 18, 0, 0, 0, 14}, - {5, 0, 0, 0, 0, 1, 14}, - {21, 0, 18, 0, 1, 0, 1}, - {22, 0, 18, 1, 1, 0, 0}, - {18, 0, 18, 1, 1, 0, 1}, - {21, 0, 18, 0, 1, 0, 5}, - {7, 0, 0, 0, 1, 33, 14}, - {7, 0, 0, 0, 1, 33, 32}, - {6, 0, 0, 0, 1, 0, 32}, - {6, 0, 0, 0, 1, 0, 5}, - {7, 0, 0, 0, 1, 24, 14}, - {23, 0, 10, 0, 0, 0, 10}, - {26, 0, 18, 0, 0, 0, 14}, - {26, 0, 18, 0, 1, 0, 12}, - {25, 0, 18, 0, 1, 0, 12}, - {1, 0, 18, 0, 5, 0, 21}, - {26, 0, 18, 0, 5, 0, 31}, - {7, 0, 0, 0, 5, 47, 12}, - {14, 0, 18, 0, 5, 2, 12}, - {15, 0, 18, 0, 5, 2, 12}, - {26, 0, 18, 0, 5, 2, 12}, - {26, 0, 0, 0, 5, 2, 12}, - {7, 0, 0, 0, 5, 73, 12}, - {7, 0, 0, 0, 5, 74, 12}, - {7, 0, 0, 0, 5, 37, 12}, - {15, 0, 0, 0, 5, 37, 12}, - {7, 0, 0, 0, 5, 38, 12}, - {14, 0, 0, 0, 5, 38, 12}, - {7, 0, 0, 0, 5, 118, 12}, - {12, 230, 13, 0, 5, 118, 21}, - {7, 0, 0, 0, 5, 48, 12}, - {21, 0, 0, 0, 5, 48, 17}, - {7, 0, 0, 0, 5, 59, 12}, - {21, 0, 0, 0, 5, 59, 17}, - {14, 0, 0, 0, 5, 59, 12}, - {9, 0, 0, 0, 5, 39, 12}, - {5, 0, 0, 0, 5, 39, 12}, - {7, 0, 0, 0, 5, 49, 12}, - {7, 0, 0, 0, 5, 50, 12}, - {13, 0, 0, 0, 5, 50, 11}, - {9, 0, 0, 0, 5, 136, 12}, - {5, 0, 0, 0, 5, 136, 12}, - {7, 0, 0, 0, 5, 106, 12}, - {7, 0, 0, 0, 5, 104, 12}, - {21, 0, 0, 0, 5, 104, 12}, - {7, 0, 0, 0, 5, 110, 12}, - {7, 0, 3, 0, 5, 51, 12}, - {7, 0, 3, 0, 5, 86, 12}, - {21, 0, 3, 0, 5, 86, 17}, - {15, 0, 3, 0, 5, 86, 12}, - {7, 0, 3, 0, 5, 120, 12}, - {26, 0, 3, 0, 5, 120, 12}, - {15, 0, 3, 0, 5, 120, 12}, - {7, 0, 3, 0, 5, 116, 12}, - {15, 0, 3, 0, 5, 116, 12}, - {7, 0, 3, 0, 5, 128, 12}, - {15, 0, 3, 0, 5, 128, 12}, - {7, 0, 3, 0, 5, 63, 12}, - {15, 0, 3, 0, 5, 63, 12}, - {21, 0, 18, 0, 5, 63, 17}, - {7, 0, 3, 0, 5, 75, 12}, - {21, 0, 3, 0, 5, 75, 12}, - {7, 0, 3, 0, 5, 97, 12}, - {7, 0, 3, 0, 5, 96, 12}, - {15, 0, 3, 0, 5, 96, 12}, - {7, 0, 3, 0, 5, 60, 12}, - {12, 0, 13, 0, 5, 60, 21}, - {12, 220, 13, 0, 5, 60, 21}, - {12, 230, 13, 0, 5, 60, 21}, - {12, 1, 13, 0, 5, 60, 21}, - {12, 9, 13, 0, 5, 60, 21}, - {15, 0, 3, 0, 5, 60, 12}, - {21, 0, 3, 0, 5, 60, 17}, - {21, 0, 3, 0, 5, 60, 12}, - {7, 0, 3, 0, 5, 87, 12}, - {15, 0, 3, 0, 5, 87, 12}, - {21, 0, 3, 0, 5, 87, 12}, - {7, 0, 3, 0, 5, 117, 12}, - {15, 0, 3, 0, 5, 117, 12}, - {7, 0, 3, 0, 5, 112, 12}, - {26, 0, 3, 0, 5, 112, 12}, - {12, 230, 13, 0, 5, 112, 21}, - {12, 220, 13, 0, 5, 112, 21}, - {15, 0, 3, 0, 5, 112, 12}, - {21, 0, 3, 0, 5, 112, 17}, - {21, 0, 3, 0, 5, 112, 15}, - {7, 0, 3, 0, 5, 79, 12}, - {21, 0, 18, 0, 5, 79, 17}, - {7, 0, 3, 0, 5, 88, 12}, - {15, 0, 3, 0, 5, 88, 12}, - {7, 0, 3, 0, 5, 89, 12}, - {15, 0, 3, 0, 5, 89, 12}, - {7, 0, 3, 0, 5, 122, 12}, - {21, 0, 3, 0, 5, 122, 12}, - {15, 0, 3, 0, 5, 122, 12}, - {7, 0, 3, 0, 5, 90, 12}, - {9, 0, 3, 0, 5, 130, 12}, - {5, 0, 3, 0, 5, 130, 12}, - {15, 0, 3, 0, 5, 130, 12}, - {15, 0, 11, 0, 5, 6, 12}, - {10, 0, 0, 0, 5, 93, 21}, - {12, 0, 13, 0, 5, 93, 21}, - {7, 0, 0, 0, 5, 93, 12}, - {12, 9, 13, 0, 5, 93, 21}, - {21, 0, 0, 0, 5, 93, 17}, - {21, 0, 0, 0, 5, 93, 12}, - {15, 0, 18, 0, 5, 93, 12}, - {13, 0, 0, 0, 5, 93, 11}, - {12, 0, 13, 0, 5, 91, 21}, - {10, 0, 0, 0, 5, 91, 21}, - {7, 0, 0, 0, 5, 91, 12}, - {12, 9, 13, 0, 5, 91, 21}, - {12, 7, 13, 0, 5, 91, 21}, - {21, 0, 0, 0, 5, 91, 12}, - {1, 0, 0, 0, 5, 91, 12}, - {21, 0, 0, 0, 5, 91, 17}, - {7, 0, 0, 0, 5, 100, 12}, - {13, 0, 0, 0, 5, 100, 11}, - {12, 230, 13, 0, 5, 95, 21}, - {7, 0, 0, 0, 5, 95, 12}, - {12, 0, 13, 0, 5, 95, 21}, - {10, 0, 0, 0, 5, 95, 21}, - {12, 9, 13, 0, 5, 95, 21}, - {13, 0, 0, 0, 5, 95, 11}, - {21, 0, 0, 0, 5, 95, 17}, - {7, 0, 0, 0, 5, 111, 12}, - {12, 7, 13, 0, 5, 111, 21}, - {21, 0, 0, 0, 5, 111, 12}, - {21, 0, 0, 0, 5, 111, 18}, - {12, 0, 13, 0, 5, 99, 21}, - {10, 0, 0, 0, 5, 99, 21}, - {7, 0, 0, 0, 5, 99, 12}, - {10, 9, 0, 0, 5, 99, 21}, - {21, 0, 0, 0, 5, 99, 17}, - {21, 0, 0, 0, 5, 99, 12}, - {12, 7, 13, 0, 5, 99, 21}, - {13, 0, 0, 0, 5, 99, 11}, - {21, 0, 0, 0, 5, 99, 18}, - {15, 0, 0, 0, 5, 18, 12}, - {7, 0, 0, 0, 5, 108, 12}, - {10, 0, 0, 0, 5, 108, 21}, - {12, 0, 13, 0, 5, 108, 21}, - {10, 9, 0, 0, 5, 108, 21}, - {12, 7, 13, 0, 5, 108, 21}, - {21, 0, 0, 0, 5, 108, 17}, - {21, 0, 0, 0, 5, 108, 12}, - {7, 0, 0, 0, 5, 129, 12}, - {21, 0, 0, 0, 5, 129, 17}, - {7, 0, 0, 0, 5, 109, 12}, - {12, 0, 13, 0, 5, 109, 21}, - {10, 0, 0, 0, 5, 109, 21}, - {12, 7, 13, 0, 5, 109, 21}, - {12, 9, 13, 0, 5, 109, 21}, - {13, 0, 0, 0, 5, 109, 11}, - {12, 0, 13, 0, 5, 107, 21}, - {10, 0, 0, 0, 5, 107, 21}, - {7, 0, 0, 0, 5, 107, 12}, - {12, 7, 13, 0, 5, 107, 21}, - {10, 9, 0, 0, 5, 107, 21}, - {12, 230, 13, 0, 5, 107, 21}, - {7, 0, 0, 0, 5, 135, 12}, - {10, 0, 0, 0, 5, 135, 21}, - {12, 0, 13, 0, 5, 135, 21}, - {12, 9, 13, 0, 5, 135, 21}, - {12, 7, 13, 0, 5, 135, 21}, - {21, 0, 0, 0, 5, 135, 17}, - {21, 0, 0, 0, 5, 135, 12}, - {13, 0, 0, 0, 5, 135, 11}, - {7, 0, 0, 0, 5, 124, 12}, - {10, 0, 0, 0, 5, 124, 21}, - {12, 0, 13, 0, 5, 124, 21}, - {12, 9, 13, 0, 5, 124, 21}, - {12, 7, 13, 0, 5, 124, 21}, - {21, 0, 0, 0, 5, 124, 12}, - {13, 0, 0, 0, 5, 124, 11}, - {7, 0, 0, 0, 5, 123, 12}, - {10, 0, 0, 0, 5, 123, 21}, - {12, 0, 13, 0, 5, 123, 21}, - {12, 9, 13, 0, 5, 123, 21}, - {12, 7, 13, 0, 5, 123, 21}, - {21, 0, 0, 0, 5, 123, 18}, - {21, 0, 0, 0, 5, 123, 17}, - {21, 0, 0, 0, 5, 123, 6}, - {21, 0, 0, 0, 5, 123, 12}, - {7, 0, 0, 0, 5, 114, 12}, - {10, 0, 0, 0, 5, 114, 21}, - {12, 0, 13, 0, 5, 114, 21}, - {12, 9, 13, 0, 5, 114, 21}, - {21, 0, 0, 0, 5, 114, 17}, - {21, 0, 0, 0, 5, 114, 12}, - {13, 0, 0, 0, 5, 114, 11}, - {21, 0, 18, 0, 5, 31, 18}, - {7, 0, 0, 0, 5, 101, 12}, - {12, 0, 13, 0, 5, 101, 21}, - {10, 0, 0, 0, 5, 101, 21}, - {10, 9, 0, 0, 5, 101, 21}, - {12, 7, 13, 0, 5, 101, 21}, - {13, 0, 0, 0, 5, 101, 11}, - {7, 0, 0, 0, 5, 126, 38}, - {12, 0, 13, 0, 5, 126, 38}, - {10, 0, 0, 0, 5, 126, 38}, - {12, 9, 13, 0, 5, 126, 38}, - {13, 0, 0, 0, 5, 126, 11}, - {15, 0, 0, 0, 5, 126, 38}, - {21, 0, 0, 0, 5, 126, 17}, - {26, 0, 0, 0, 5, 126, 38}, - {9, 0, 0, 0, 5, 125, 12}, - {5, 0, 0, 0, 5, 125, 12}, - {13, 0, 0, 0, 5, 125, 11}, - {15, 0, 0, 0, 5, 125, 12}, - {7, 0, 0, 0, 5, 125, 12}, - {7, 0, 0, 0, 5, 121, 12}, - {7, 0, 0, 0, 5, 133, 12}, - {10, 0, 0, 0, 5, 133, 21}, - {12, 0, 13, 0, 5, 133, 21}, - {12, 9, 0, 0, 5, 133, 21}, - {21, 0, 0, 0, 5, 133, 17}, - {13, 0, 0, 0, 5, 133, 11}, - {15, 0, 0, 0, 5, 133, 12}, - {21, 0, 0, 0, 5, 134, 18}, - {21, 0, 0, 0, 5, 134, 6}, - {7, 0, 0, 0, 5, 134, 12}, - {12, 0, 13, 0, 5, 134, 21}, - {10, 0, 0, 0, 5, 134, 21}, - {7, 0, 0, 0, 5, 62, 12}, - {14, 0, 0, 0, 5, 62, 12}, - {21, 0, 0, 0, 5, 62, 17}, - {7, 0, 0, 0, 5, 80, 12}, - {7, 0, 0, 0, 5, 80, 0}, - {7, 0, 0, 0, 5, 80, 1}, - {7, 0, 0, 0, 5, 127, 12}, - {7, 0, 0, 0, 5, 127, 0}, - {7, 0, 0, 0, 5, 127, 1}, - {7, 0, 0, 0, 5, 115, 12}, - {13, 0, 0, 0, 5, 115, 11}, - {21, 0, 0, 0, 5, 115, 17}, - {7, 0, 0, 0, 5, 103, 12}, - {12, 1, 13, 0, 5, 103, 21}, - {21, 0, 0, 0, 5, 103, 17}, - {7, 0, 0, 0, 5, 119, 12}, - {12, 230, 13, 0, 5, 119, 21}, - {21, 0, 0, 0, 5, 119, 17}, - {21, 0, 0, 0, 5, 119, 12}, - {26, 0, 0, 0, 5, 119, 12}, - {6, 0, 0, 0, 5, 119, 12}, - {13, 0, 0, 0, 5, 119, 11}, - {15, 0, 0, 0, 5, 119, 12}, - {7, 0, 0, 0, 5, 98, 12}, - {10, 0, 0, 0, 5, 98, 21}, - {12, 0, 13, 0, 5, 98, 21}, - {6, 0, 0, 0, 5, 98, 12}, - {6, 0, 0, 0, 2, 137, 5}, - {7, 0, 0, 0, 2, 137, 14}, - {7, 0, 0, 0, 5, 105, 12}, - {26, 0, 0, 0, 5, 105, 12}, - {12, 0, 13, 0, 5, 105, 21}, - {12, 1, 13, 0, 5, 105, 21}, - {21, 0, 0, 0, 5, 105, 17}, - {10, 216, 0, 0, 5, 0, 21}, - {10, 226, 0, 0, 5, 0, 21}, - {12, 230, 13, 0, 5, 2, 21}, - {25, 0, 0, 0, 5, 0, 12}, - {13, 0, 8, 0, 5, 0, 11}, - {26, 0, 0, 0, 5, 131, 12}, - {12, 0, 13, 0, 5, 131, 21}, - {21, 0, 0, 0, 5, 131, 17}, - {21, 0, 0, 0, 5, 131, 12}, - {12, 230, 13, 0, 5, 56, 21}, - {7, 0, 3, 0, 5, 113, 12}, - {15, 0, 3, 0, 5, 113, 12}, - {12, 220, 13, 0, 5, 113, 21}, - {9, 0, 3, 0, 5, 132, 12}, - {5, 0, 3, 0, 5, 132, 12}, - {12, 230, 13, 0, 5, 132, 21}, - {12, 7, 13, 0, 5, 132, 21}, - {13, 0, 3, 0, 5, 132, 11}, - {21, 0, 3, 0, 5, 132, 0}, - {2, 0, 18, 0, 5, 102, 14}, - {26, 0, 0, 0, 2, 0, 29}, - {26, 0, 0, 0, 5, 0, 28}, - {26, 0, 0, 0, 2, 32, 14}, - {24, 0, 18, 0, 2, 0, 41}, - {26, 0, 18, 0, 5, 0, 5}, + {2, 0, 18, 5, 102, 39}, + {0, 0, 14, 5, 0, 21}, + {0, 0, 16, 5, 0, 17}, + {0, 0, 15, 5, 0, 34}, + {0, 0, 16, 5, 0, 30}, + {0, 0, 17, 5, 0, 30}, + {0, 0, 15, 5, 0, 33}, + {0, 0, 15, 5, 0, 21}, + {0, 0, 16, 5, 0, 21}, + {29, 0, 17, 3, 0, 38}, + {21, 0, 18, 3, 0, 6}, + {21, 0, 18, 3, 0, 3}, + {21, 0, 10, 3, 0, 12}, + {23, 0, 10, 3, 0, 9}, + {21, 0, 10, 3, 0, 10}, + {21, 0, 18, 3, 0, 12}, + {22, 0, 18, 3, 0, 0}, + {18, 0, 18, 3, 0, 2}, + {25, 0, 9, 3, 0, 9}, + {21, 0, 12, 3, 0, 8}, + {17, 0, 9, 3, 0, 16}, + {21, 0, 12, 3, 0, 7}, + {13, 0, 8, 3, 0, 11}, + {21, 0, 18, 3, 0, 8}, + {25, 0, 18, 3, 0, 12}, + {9, 0, 0, 3, 1, 12}, + {21, 0, 18, 3, 0, 9}, + {24, 0, 18, 3, 0, 12}, + {16, 0, 18, 3, 0, 12}, + {5, 0, 0, 3, 1, 12}, + {25, 0, 18, 3, 0, 17}, + {18, 0, 18, 3, 0, 1}, + {0, 0, 15, 5, 0, 35}, + {29, 0, 12, 5, 0, 4}, + {21, 0, 18, 4, 0, 0}, + {23, 0, 10, 3, 0, 10}, + {23, 0, 10, 4, 0, 9}, + {26, 0, 18, 3, 0, 12}, + {21, 0, 18, 4, 0, 29}, + {24, 0, 18, 4, 0, 29}, + {26, 0, 18, 5, 0, 12}, + {7, 0, 0, 4, 1, 29}, + {20, 0, 18, 5, 0, 3}, + {1, 0, 14, 4, 0, 17}, + {26, 0, 18, 4, 0, 12}, + {26, 0, 10, 4, 0, 10}, + {25, 0, 10, 4, 0, 9}, + {15, 0, 8, 4, 0, 29}, + {24, 0, 18, 4, 0, 18}, + {5, 0, 0, 5, 0, 12}, + {19, 0, 18, 5, 0, 3}, + {15, 0, 18, 4, 0, 29}, + {9, 0, 0, 5, 1, 12}, + {9, 0, 0, 4, 1, 12}, + {25, 0, 18, 4, 0, 29}, + {5, 0, 0, 4, 1, 12}, + {5, 0, 0, 5, 1, 12}, + {7, 0, 0, 5, 1, 12}, + {8, 0, 0, 5, 1, 12}, + {6, 0, 0, 5, 1, 12}, + {6, 0, 18, 5, 0, 12}, + {6, 0, 0, 5, 0, 12}, + {24, 0, 18, 5, 0, 12}, + {24, 0, 18, 4, 0, 12}, + {6, 0, 18, 4, 0, 29}, + {6, 0, 18, 5, 0, 18}, + {6, 0, 0, 4, 0, 29}, + {24, 0, 18, 5, 34, 12}, + {12, 230, 13, 4, 40, 21}, + {12, 232, 13, 4, 40, 21}, + {12, 220, 13, 4, 40, 21}, + {12, 216, 13, 4, 40, 21}, + {12, 202, 13, 4, 40, 21}, + {12, 1, 13, 4, 40, 21}, + {12, 240, 13, 4, 40, 21}, + {12, 0, 13, 4, 40, 4}, + {12, 233, 13, 4, 40, 4}, + {12, 234, 13, 4, 40, 4}, + {9, 0, 0, 5, 2, 12}, + {5, 0, 0, 5, 2, 12}, + {24, 0, 18, 5, 2, 12}, + {2, 0, 18, 5, 102, 39}, + {6, 0, 0, 5, 2, 12}, + {21, 0, 18, 5, 0, 8}, + {21, 0, 18, 5, 0, 12}, + {9, 0, 0, 4, 2, 12}, + {5, 0, 0, 4, 2, 12}, + {9, 0, 0, 5, 54, 12}, + {5, 0, 0, 5, 54, 12}, + {25, 0, 18, 5, 2, 12}, + {9, 0, 0, 5, 3, 12}, + {9, 0, 0, 4, 3, 12}, + {5, 0, 0, 4, 3, 12}, + {5, 0, 0, 5, 3, 12}, + {26, 0, 0, 5, 3, 12}, + {12, 230, 13, 5, 3, 21}, + {12, 230, 13, 5, 40, 21}, + {11, 0, 13, 5, 3, 21}, + {9, 0, 0, 5, 4, 12}, + {6, 0, 0, 5, 4, 12}, + {21, 0, 0, 5, 4, 12}, + {5, 0, 0, 5, 4, 12}, + {21, 0, 0, 5, 0, 8}, + {17, 0, 18, 5, 4, 17}, + {26, 0, 18, 5, 4, 12}, + {23, 0, 10, 5, 4, 9}, + {12, 220, 13, 5, 5, 21}, + {12, 230, 13, 5, 5, 21}, + {12, 222, 13, 5, 5, 21}, + {12, 228, 13, 5, 5, 21}, + {12, 10, 13, 5, 5, 21}, + {12, 11, 13, 5, 5, 21}, + {12, 12, 13, 5, 5, 21}, + {12, 13, 13, 5, 5, 21}, + {12, 14, 13, 5, 5, 21}, + {12, 15, 13, 5, 5, 21}, + {12, 16, 13, 5, 5, 21}, + {12, 17, 13, 5, 5, 21}, + {12, 18, 13, 5, 5, 21}, + {12, 19, 13, 5, 5, 21}, + {12, 20, 13, 5, 5, 21}, + {12, 21, 13, 5, 5, 21}, + {12, 22, 13, 5, 5, 21}, + {17, 0, 3, 5, 5, 17}, + {12, 23, 13, 5, 5, 21}, + {21, 0, 3, 5, 5, 12}, + {12, 24, 13, 5, 5, 21}, + {12, 25, 13, 5, 5, 21}, + {21, 0, 3, 5, 5, 6}, + {7, 0, 3, 5, 5, 13}, + {1, 0, 11, 5, 6, 12}, + {1, 0, 11, 5, 0, 12}, + {25, 0, 18, 5, 6, 12}, + {25, 0, 4, 5, 6, 12}, + {21, 0, 10, 5, 6, 10}, + {23, 0, 4, 5, 6, 10}, + {21, 0, 12, 5, 0, 8}, + {21, 0, 4, 5, 6, 8}, + {26, 0, 18, 5, 6, 12}, + {12, 230, 13, 5, 6, 21}, + {12, 30, 13, 5, 6, 21}, + {12, 31, 13, 5, 6, 21}, + {12, 32, 13, 5, 6, 21}, + {21, 0, 4, 5, 0, 6}, + {1, 0, 4, 5, 6, 21}, + {21, 0, 4, 5, 6, 6}, + {7, 0, 4, 5, 6, 12}, + {6, 0, 4, 5, 0, 12}, + {12, 27, 13, 5, 40, 21}, + {12, 28, 13, 5, 40, 21}, + {12, 29, 13, 5, 40, 21}, + {12, 30, 13, 5, 40, 21}, + {12, 31, 13, 5, 40, 21}, + {12, 32, 13, 5, 40, 21}, + {12, 33, 13, 5, 40, 21}, + {12, 34, 13, 5, 40, 21}, + {12, 220, 13, 5, 40, 21}, + {12, 220, 13, 5, 6, 21}, + {13, 0, 11, 5, 6, 11}, + {21, 0, 11, 5, 6, 11}, + {21, 0, 4, 5, 6, 12}, + {12, 35, 13, 5, 40, 21}, + {6, 0, 4, 5, 6, 12}, + {13, 0, 8, 5, 6, 11}, + {26, 0, 4, 5, 6, 12}, + {21, 0, 4, 5, 7, 12}, + {1, 0, 4, 5, 7, 12}, + {7, 0, 4, 5, 7, 12}, + {12, 36, 13, 5, 7, 21}, + {12, 230, 13, 5, 7, 21}, + {12, 220, 13, 5, 7, 21}, + {7, 0, 4, 5, 8, 12}, + {12, 0, 13, 5, 8, 21}, + {13, 0, 3, 5, 65, 11}, + {7, 0, 3, 5, 65, 12}, + {12, 230, 13, 5, 65, 21}, + {12, 220, 13, 5, 65, 21}, + {6, 0, 3, 5, 65, 12}, + {26, 0, 18, 5, 65, 12}, + {21, 0, 18, 5, 65, 12}, + {21, 0, 18, 5, 65, 8}, + {21, 0, 18, 5, 65, 6}, + {7, 0, 3, 5, 81, 12}, + {12, 230, 13, 5, 81, 21}, + {6, 0, 3, 5, 81, 12}, + {21, 0, 3, 5, 81, 12}, + {7, 0, 3, 5, 94, 12}, + {12, 220, 13, 5, 94, 21}, + {21, 0, 3, 5, 94, 12}, + {12, 27, 13, 5, 6, 21}, + {12, 28, 13, 5, 6, 21}, + {12, 29, 13, 5, 6, 21}, + {12, 0, 13, 5, 9, 21}, + {10, 0, 0, 5, 9, 21}, + {7, 0, 0, 5, 9, 12}, + {12, 7, 13, 5, 9, 21}, + {12, 9, 13, 5, 9, 21}, + {12, 230, 13, 5, 9, 21}, + {21, 0, 0, 5, 0, 17}, + {13, 0, 0, 5, 9, 11}, + {21, 0, 0, 5, 9, 12}, + {6, 0, 0, 5, 9, 12}, + {7, 0, 0, 5, 10, 12}, + {12, 0, 13, 5, 10, 21}, + {10, 0, 0, 5, 10, 21}, + {12, 7, 13, 5, 10, 21}, + {12, 9, 13, 5, 10, 21}, + {13, 0, 0, 5, 10, 11}, + {23, 0, 10, 5, 10, 10}, + {15, 0, 0, 5, 10, 12}, + {15, 0, 0, 5, 10, 10}, + {26, 0, 0, 5, 10, 12}, + {23, 0, 10, 5, 10, 9}, + {21, 0, 0, 5, 10, 12}, + {12, 0, 13, 5, 11, 21}, + {10, 0, 0, 5, 11, 21}, + {7, 0, 0, 5, 11, 12}, + {12, 7, 13, 5, 11, 21}, + {12, 9, 13, 5, 11, 21}, + {13, 0, 0, 5, 11, 11}, + {12, 0, 13, 5, 12, 21}, + {10, 0, 0, 5, 12, 21}, + {7, 0, 0, 5, 12, 12}, + {12, 7, 13, 5, 12, 21}, + {12, 9, 13, 5, 12, 21}, + {13, 0, 0, 5, 12, 11}, + {21, 0, 0, 5, 12, 12}, + {23, 0, 10, 5, 12, 9}, + {12, 0, 13, 5, 13, 21}, + {10, 0, 0, 5, 13, 21}, + {7, 0, 0, 5, 13, 12}, + {12, 7, 13, 5, 13, 21}, + {12, 9, 13, 5, 13, 21}, + {13, 0, 0, 5, 13, 11}, + {26, 0, 0, 5, 13, 12}, + {15, 0, 0, 5, 13, 12}, + {12, 0, 13, 5, 14, 21}, + {7, 0, 0, 5, 14, 12}, + {10, 0, 0, 5, 14, 21}, + {12, 9, 13, 5, 14, 21}, + {13, 0, 0, 5, 14, 11}, + {15, 0, 0, 5, 14, 12}, + {26, 0, 18, 5, 14, 12}, + {23, 0, 10, 5, 14, 9}, + {12, 0, 13, 5, 15, 21}, + {10, 0, 0, 5, 15, 21}, + {7, 0, 0, 5, 15, 12}, + {12, 9, 13, 5, 15, 21}, + {12, 84, 13, 5, 15, 21}, + {12, 91, 13, 5, 15, 21}, + {13, 0, 0, 5, 15, 11}, + {15, 0, 18, 5, 15, 12}, + {26, 0, 0, 5, 15, 12}, + {7, 0, 0, 5, 16, 12}, + {12, 0, 13, 5, 16, 21}, + {10, 0, 0, 5, 16, 21}, + {12, 7, 13, 5, 16, 21}, + {12, 0, 0, 5, 16, 21}, + {12, 9, 13, 5, 16, 21}, + {13, 0, 0, 5, 16, 11}, + {12, 0, 13, 5, 17, 21}, + {10, 0, 0, 5, 17, 21}, + {7, 0, 0, 5, 17, 12}, + {12, 9, 13, 5, 17, 21}, + {26, 0, 0, 5, 17, 12}, + {15, 0, 0, 5, 17, 12}, + {13, 0, 0, 5, 17, 11}, + {26, 0, 0, 5, 17, 10}, + {10, 0, 0, 5, 18, 21}, + {7, 0, 0, 5, 18, 12}, + {12, 9, 13, 5, 18, 21}, + {12, 0, 13, 5, 18, 21}, + {13, 0, 0, 5, 18, 11}, + {21, 0, 0, 5, 18, 12}, + {7, 0, 0, 5, 19, 36}, + {12, 0, 13, 5, 19, 36}, + {12, 103, 13, 5, 19, 36}, + {12, 9, 13, 5, 19, 36}, + {23, 0, 10, 5, 0, 9}, + {6, 0, 0, 5, 19, 36}, + {12, 107, 13, 5, 19, 36}, + {21, 0, 0, 5, 19, 12}, + {13, 0, 0, 5, 19, 11}, + {21, 0, 0, 5, 19, 17}, + {7, 0, 0, 5, 20, 36}, + {12, 0, 13, 5, 20, 36}, + {12, 118, 13, 5, 20, 36}, + {6, 0, 0, 5, 20, 36}, + {12, 122, 13, 5, 20, 36}, + {13, 0, 0, 5, 20, 11}, + {7, 0, 0, 5, 21, 12}, + {26, 0, 0, 5, 21, 18}, + {21, 0, 0, 5, 21, 18}, + {21, 0, 0, 5, 21, 12}, + {21, 0, 0, 5, 21, 4}, + {21, 0, 0, 5, 21, 17}, + {21, 0, 0, 5, 21, 6}, + {26, 0, 0, 5, 21, 12}, + {12, 220, 13, 5, 21, 21}, + {13, 0, 0, 5, 21, 11}, + {15, 0, 0, 5, 21, 12}, + {26, 0, 0, 5, 21, 17}, + {12, 216, 13, 5, 21, 21}, + {22, 0, 18, 5, 21, 0}, + {18, 0, 18, 5, 21, 1}, + {10, 0, 0, 5, 21, 21}, + {12, 129, 13, 5, 21, 21}, + {12, 130, 13, 5, 21, 21}, + {12, 0, 13, 5, 21, 21}, + {12, 132, 13, 5, 21, 21}, + {10, 0, 0, 5, 21, 17}, + {12, 230, 13, 5, 21, 21}, + {12, 9, 13, 5, 21, 21}, + {26, 0, 0, 5, 0, 12}, + {7, 0, 0, 5, 22, 36}, + {10, 0, 0, 5, 22, 36}, + {12, 0, 13, 5, 22, 36}, + {12, 7, 13, 5, 22, 36}, + {12, 9, 13, 5, 22, 36}, + {13, 0, 0, 5, 22, 11}, + {21, 0, 0, 5, 22, 17}, + {21, 0, 0, 5, 22, 12}, + {12, 220, 13, 5, 22, 36}, + {26, 0, 0, 5, 22, 36}, + {9, 0, 0, 5, 23, 12}, + {7, 0, 0, 5, 23, 12}, + {21, 0, 0, 5, 0, 12}, + {6, 0, 0, 5, 23, 12}, + {7, 0, 0, 2, 24, 25}, + {7, 0, 0, 5, 24, 26}, + {7, 0, 0, 5, 24, 27}, + {7, 0, 0, 5, 25, 12}, + {12, 230, 13, 5, 25, 21}, + {21, 0, 0, 5, 25, 12}, + {21, 0, 0, 5, 25, 17}, + {15, 0, 0, 5, 25, 12}, + {26, 0, 18, 5, 25, 12}, + {9, 0, 0, 5, 26, 12}, + {5, 0, 0, 5, 26, 12}, + {17, 0, 18, 5, 27, 17}, + {7, 0, 0, 5, 27, 12}, + {21, 0, 0, 5, 27, 12}, + {29, 0, 17, 5, 28, 17}, + {7, 0, 0, 5, 28, 12}, + {22, 0, 18, 5, 28, 0}, + {18, 0, 18, 5, 28, 1}, + {7, 0, 0, 5, 29, 12}, + {14, 0, 0, 5, 29, 12}, + {7, 0, 0, 5, 41, 12}, + {12, 0, 13, 5, 41, 21}, + {12, 9, 13, 5, 41, 21}, + {7, 0, 0, 5, 42, 12}, + {12, 0, 13, 5, 42, 21}, + {12, 9, 13, 5, 42, 21}, + {7, 0, 0, 5, 43, 12}, + {12, 0, 13, 5, 43, 21}, + {7, 0, 0, 5, 44, 12}, + {12, 0, 13, 5, 44, 21}, + {7, 0, 0, 5, 30, 36}, + {12, 0, 13, 5, 30, 36}, + {10, 0, 0, 5, 30, 36}, + {12, 9, 13, 5, 30, 36}, + {21, 0, 0, 5, 30, 17}, + {21, 0, 0, 5, 30, 5}, + {6, 0, 0, 5, 30, 36}, + {21, 0, 0, 5, 30, 12}, + {23, 0, 10, 5, 30, 9}, + {12, 230, 13, 5, 30, 36}, + {13, 0, 0, 5, 30, 11}, + {15, 0, 18, 5, 30, 12}, + {21, 0, 18, 5, 31, 12}, + {21, 0, 18, 5, 0, 6}, + {21, 0, 18, 5, 31, 17}, + {21, 0, 18, 5, 0, 17}, + {17, 0, 18, 5, 31, 18}, + {21, 0, 18, 5, 31, 6}, + {12, 0, 13, 5, 31, 21}, + {1, 0, 14, 5, 31, 4}, + {13, 0, 0, 5, 31, 11}, + {7, 0, 0, 5, 31, 12}, + {6, 0, 0, 5, 31, 12}, + {12, 228, 13, 5, 31, 21}, + {7, 0, 0, 5, 45, 12}, + {12, 0, 13, 5, 45, 21}, + {10, 0, 0, 5, 45, 21}, + {12, 222, 13, 5, 45, 21}, + {12, 230, 13, 5, 45, 21}, + {12, 220, 13, 5, 45, 21}, + {26, 0, 18, 5, 45, 12}, + {21, 0, 18, 5, 45, 6}, + {13, 0, 0, 5, 45, 11}, + {7, 0, 0, 5, 46, 36}, + {7, 0, 0, 5, 55, 36}, + {13, 0, 0, 5, 55, 11}, + {15, 0, 0, 5, 55, 36}, + {26, 0, 18, 5, 55, 36}, + {26, 0, 18, 5, 30, 12}, + {7, 0, 0, 5, 53, 12}, + {12, 230, 13, 5, 53, 21}, + {12, 220, 13, 5, 53, 21}, + {10, 0, 0, 5, 53, 21}, + {12, 0, 13, 5, 53, 21}, + {21, 0, 0, 5, 53, 12}, + {7, 0, 0, 5, 77, 36}, + {10, 0, 0, 5, 77, 36}, + {12, 0, 13, 5, 77, 36}, + {12, 9, 13, 5, 77, 36}, + {12, 230, 13, 5, 77, 36}, + {12, 220, 13, 5, 77, 21}, + {13, 0, 0, 5, 77, 11}, + {21, 0, 0, 5, 77, 36}, + {6, 0, 0, 5, 77, 36}, + {11, 0, 13, 5, 40, 21}, + {12, 0, 13, 5, 61, 21}, + {10, 0, 0, 5, 61, 21}, + {7, 0, 0, 5, 61, 12}, + {12, 7, 13, 5, 61, 21}, + {10, 9, 0, 5, 61, 21}, + {13, 0, 0, 5, 61, 11}, + {21, 0, 0, 5, 61, 17}, + {21, 0, 0, 5, 61, 12}, + {26, 0, 0, 5, 61, 12}, + {12, 230, 13, 5, 61, 21}, + {12, 220, 13, 5, 61, 21}, + {12, 0, 13, 5, 66, 21}, + {10, 0, 0, 5, 66, 21}, + {7, 0, 0, 5, 66, 12}, + {10, 9, 0, 5, 66, 21}, + {12, 9, 13, 5, 66, 21}, + {13, 0, 0, 5, 66, 11}, + {7, 0, 0, 5, 92, 12}, + {12, 7, 13, 5, 92, 21}, + {10, 0, 0, 5, 92, 21}, + {12, 0, 13, 5, 92, 21}, + {10, 9, 0, 5, 92, 21}, + {21, 0, 0, 5, 92, 12}, + {7, 0, 0, 5, 67, 12}, + {10, 0, 0, 5, 67, 21}, + {12, 0, 13, 5, 67, 21}, + {12, 7, 13, 5, 67, 21}, + {21, 0, 0, 5, 67, 17}, + {13, 0, 0, 5, 67, 11}, + {13, 0, 0, 5, 68, 11}, + {7, 0, 0, 5, 68, 12}, + {6, 0, 0, 5, 68, 12}, + {21, 0, 0, 5, 68, 17}, + {21, 0, 0, 5, 66, 12}, + {12, 1, 13, 5, 40, 21}, + {10, 0, 0, 5, 0, 21}, + {7, 0, 0, 5, 0, 12}, + {6, 0, 0, 5, 3, 12}, + {12, 234, 13, 5, 40, 21}, + {12, 214, 13, 5, 40, 21}, + {12, 202, 13, 5, 40, 21}, + {12, 232, 13, 5, 40, 21}, + {12, 228, 13, 5, 40, 21}, + {12, 233, 13, 5, 40, 21}, + {8, 0, 0, 5, 2, 12}, + {24, 0, 18, 5, 2, 18}, + {29, 0, 17, 5, 0, 17}, + {29, 0, 17, 5, 0, 4}, + {1, 0, 14, 5, 0, 20}, + {1, 0, 14, 5, 40, 21}, + {1, 0, 14, 5, 40, 40}, + {1, 0, 0, 5, 0, 21}, + {1, 0, 3, 5, 0, 21}, + {17, 0, 18, 4, 0, 17}, + {17, 0, 18, 5, 0, 4}, + {17, 0, 18, 5, 0, 17}, + {17, 0, 18, 4, 0, 19}, + {17, 0, 18, 4, 0, 29}, + {20, 0, 18, 4, 0, 3}, + {19, 0, 18, 4, 0, 3}, + {22, 0, 18, 5, 0, 0}, + {21, 0, 18, 4, 0, 12}, + {21, 0, 18, 4, 0, 15}, + {21, 0, 18, 4, 0, 17}, + {27, 0, 17, 5, 0, 30}, + {28, 0, 15, 5, 0, 30}, + {1, 0, 1, 5, 0, 21}, + {1, 0, 5, 5, 0, 21}, + {1, 0, 7, 5, 0, 21}, + {1, 0, 2, 5, 0, 21}, + {1, 0, 6, 5, 0, 21}, + {21, 0, 10, 4, 0, 10}, + {21, 0, 10, 5, 0, 10}, + {21, 0, 18, 4, 0, 10}, + {21, 0, 18, 5, 0, 10}, + {21, 0, 18, 5, 0, 5}, + {16, 0, 18, 5, 0, 12}, + {25, 0, 12, 5, 0, 8}, + {18, 0, 18, 5, 0, 1}, + {25, 0, 18, 5, 0, 12}, + {1, 0, 14, 5, 0, 22}, + {1, 0, 14, 5, 0, 12}, + {1, 0, 19, 5, 0, 21}, + {1, 0, 20, 5, 0, 21}, + {1, 0, 21, 5, 0, 21}, + {1, 0, 22, 5, 0, 21}, + {1, 0, 14, 5, 0, 21}, + {15, 0, 8, 5, 0, 12}, + {25, 0, 9, 5, 0, 12}, + {6, 0, 0, 4, 1, 29}, + {23, 0, 10, 5, 0, 10}, + {23, 0, 10, 1, 0, 9}, + {2, 0, 18, 5, 102, 9}, + {9, 0, 0, 5, 0, 12}, + {26, 0, 18, 4, 0, 10}, + {26, 0, 18, 4, 0, 29}, + {5, 0, 0, 4, 0, 29}, + {26, 0, 18, 4, 0, 9}, + {9, 0, 0, 4, 1, 29}, + {26, 0, 10, 5, 0, 12}, + {15, 0, 18, 5, 0, 12}, + {15, 0, 18, 4, 0, 12}, + {15, 0, 18, 5, 0, 29}, + {14, 0, 0, 4, 1, 29}, + {14, 0, 0, 5, 1, 12}, + {25, 0, 9, 5, 0, 9}, + {25, 0, 10, 5, 0, 9}, + {25, 0, 18, 5, 0, 15}, + {26, 0, 18, 2, 0, 14}, + {22, 0, 18, 2, 0, 0}, + {18, 0, 18, 2, 0, 1}, + {26, 0, 18, 2, 0, 12}, + {26, 0, 18, 5, 0, 14}, + {26, 0, 0, 4, 0, 29}, + {26, 0, 18, 5, 0, 29}, + {25, 0, 18, 2, 0, 12}, + {26, 0, 18, 4, 0, 14}, + {26, 0, 18, 5, 0, 41}, + {26, 0, 18, 4, 0, 41}, + {26, 0, 18, 2, 0, 41}, + {26, 0, 18, 2, 0, 29}, + {26, 0, 18, 5, 0, 3}, + {26, 0, 18, 5, 0, 6}, + {26, 0, 0, 5, 52, 12}, + {9, 0, 0, 5, 56, 12}, + {5, 0, 0, 5, 56, 12}, + {26, 0, 18, 5, 54, 12}, + {12, 230, 13, 5, 54, 21}, + {21, 0, 18, 5, 54, 6}, + {21, 0, 18, 5, 54, 17}, + {15, 0, 18, 5, 54, 12}, + {5, 0, 0, 5, 23, 12}, + {7, 0, 0, 5, 57, 12}, + {6, 0, 0, 5, 57, 12}, + {21, 0, 0, 5, 57, 17}, + {12, 9, 13, 5, 57, 21}, + {21, 0, 18, 5, 0, 3}, + {21, 0, 18, 5, 0, 0}, + {17, 0, 18, 5, 0, 12}, + {17, 0, 18, 5, 0, 19}, + {26, 0, 18, 2, 35, 14}, + {29, 0, 17, 0, 0, 17}, + {21, 0, 18, 2, 0, 1}, + {21, 0, 18, 2, 0, 14}, + {6, 0, 0, 2, 35, 5}, + {7, 0, 0, 2, 0, 14}, + {14, 0, 0, 2, 35, 14}, + {17, 0, 18, 2, 0, 5}, + {12, 218, 13, 2, 40, 21}, + {12, 228, 13, 2, 40, 21}, + {12, 232, 13, 2, 40, 21}, + {12, 222, 13, 2, 40, 21}, + {10, 224, 0, 2, 24, 21}, + {17, 0, 18, 2, 0, 14}, + {6, 0, 0, 2, 0, 14}, + {6, 0, 0, 2, 0, 21}, + {7, 0, 0, 2, 0, 5}, + {7, 0, 0, 2, 32, 32}, + {7, 0, 0, 2, 32, 14}, + {12, 8, 13, 2, 40, 21}, + {24, 0, 18, 2, 0, 5}, + {6, 0, 0, 2, 32, 5}, + {7, 0, 0, 2, 33, 32}, + {7, 0, 0, 2, 33, 14}, + {21, 0, 18, 2, 0, 5}, + {6, 0, 0, 2, 0, 32}, + {6, 0, 0, 2, 33, 5}, + {7, 0, 0, 2, 34, 14}, + {7, 0, 0, 2, 24, 14}, + {26, 0, 0, 2, 0, 14}, + {15, 0, 0, 2, 0, 14}, + {26, 0, 0, 2, 24, 14}, + {26, 0, 18, 2, 24, 14}, + {15, 0, 0, 4, 0, 29}, + {15, 0, 18, 2, 0, 14}, + {26, 0, 0, 2, 33, 14}, + {7, 0, 0, 2, 35, 14}, + {2, 0, 18, 2, 102, 14}, + {7, 0, 0, 2, 36, 14}, + {6, 0, 0, 2, 36, 5}, + {26, 0, 18, 2, 36, 14}, + {7, 0, 0, 5, 82, 12}, + {6, 0, 0, 5, 82, 12}, + {21, 0, 0, 5, 82, 17}, + {7, 0, 0, 5, 69, 12}, + {6, 0, 0, 5, 69, 12}, + {21, 0, 18, 5, 69, 17}, + {21, 0, 18, 5, 69, 6}, + {13, 0, 0, 5, 69, 11}, + {7, 0, 0, 5, 3, 12}, + {21, 0, 18, 5, 3, 12}, + {6, 0, 18, 5, 3, 12}, + {7, 0, 0, 5, 83, 12}, + {14, 0, 0, 5, 83, 12}, + {12, 230, 13, 5, 83, 21}, + {21, 0, 0, 5, 83, 12}, + {21, 0, 0, 5, 83, 17}, + {24, 0, 0, 5, 0, 12}, + {7, 0, 0, 5, 58, 12}, + {12, 0, 13, 5, 58, 21}, + {12, 9, 13, 5, 58, 21}, + {10, 0, 0, 5, 58, 21}, + {26, 0, 18, 5, 58, 12}, + {15, 0, 0, 5, 0, 12}, + {7, 0, 0, 5, 64, 12}, + {21, 0, 18, 5, 64, 18}, + {21, 0, 18, 5, 64, 6}, + {10, 0, 0, 5, 70, 21}, + {7, 0, 0, 5, 70, 12}, + {12, 9, 13, 5, 70, 21}, + {12, 0, 13, 5, 70, 21}, + {21, 0, 0, 5, 70, 17}, + {13, 0, 0, 5, 70, 11}, + {21, 0, 0, 5, 9, 18}, + {13, 0, 0, 5, 71, 11}, + {7, 0, 0, 5, 71, 12}, + {12, 0, 13, 5, 71, 21}, + {12, 220, 13, 5, 71, 21}, + {21, 0, 0, 5, 71, 17}, + {7, 0, 0, 5, 72, 12}, + {12, 0, 13, 5, 72, 21}, + {10, 0, 0, 5, 72, 21}, + {10, 9, 0, 5, 72, 21}, + {21, 0, 0, 5, 72, 12}, + {12, 0, 13, 5, 84, 21}, + {10, 0, 0, 5, 84, 21}, + {7, 0, 0, 5, 84, 12}, + {12, 7, 13, 5, 84, 21}, + {10, 9, 0, 5, 84, 21}, + {21, 0, 0, 5, 84, 12}, + {21, 0, 0, 5, 84, 17}, + {13, 0, 0, 5, 84, 11}, + {6, 0, 0, 5, 22, 36}, + {7, 0, 0, 5, 76, 12}, + {12, 0, 13, 5, 76, 21}, + {10, 0, 0, 5, 76, 21}, + {13, 0, 0, 5, 76, 11}, + {21, 0, 0, 5, 76, 12}, + {21, 0, 0, 5, 76, 17}, + {7, 0, 0, 5, 78, 36}, + {12, 230, 13, 5, 78, 36}, + {12, 220, 13, 5, 78, 36}, + {6, 0, 0, 5, 78, 36}, + {21, 0, 0, 5, 78, 36}, + {7, 0, 0, 5, 85, 12}, + {10, 0, 0, 5, 85, 21}, + {12, 0, 13, 5, 85, 21}, + {21, 0, 0, 5, 85, 17}, + {6, 0, 0, 5, 85, 12}, + {12, 9, 13, 5, 85, 21}, + {13, 0, 0, 5, 85, 11}, + {7, 0, 0, 2, 24, 23}, + {7, 0, 0, 2, 24, 24}, + {4, 0, 0, 5, 102, 37}, + {3, 0, 0, 4, 102, 39}, + {12, 26, 13, 5, 5, 21}, + {25, 0, 9, 5, 5, 12}, + {24, 0, 4, 5, 6, 12}, + {12, 0, 13, 4, 40, 21}, + {21, 0, 18, 2, 0, 8}, + {21, 0, 18, 2, 0, 6}, + {21, 0, 18, 2, 0, 15}, + {16, 0, 18, 2, 0, 14}, + {21, 0, 12, 2, 0, 1}, + {21, 0, 12, 2, 0, 5}, + {21, 0, 10, 2, 0, 14}, + {25, 0, 9, 2, 0, 14}, + {17, 0, 9, 2, 0, 14}, + {25, 0, 18, 2, 0, 14}, + {23, 0, 10, 2, 0, 9}, + {21, 0, 10, 2, 0, 10}, + {21, 0, 18, 0, 0, 6}, + {21, 0, 18, 0, 0, 14}, + {21, 0, 10, 0, 0, 14}, + {23, 0, 10, 0, 0, 9}, + {21, 0, 10, 0, 0, 10}, + {22, 0, 18, 0, 0, 0}, + {18, 0, 18, 0, 0, 1}, + {25, 0, 9, 0, 0, 14}, + {21, 0, 12, 0, 0, 1}, + {17, 0, 9, 0, 0, 14}, + {21, 0, 12, 0, 0, 14}, + {13, 0, 8, 0, 0, 14}, + {21, 0, 12, 0, 0, 5}, + {21, 0, 18, 0, 0, 5}, + {25, 0, 18, 0, 0, 14}, + {9, 0, 0, 0, 1, 14}, + {24, 0, 18, 0, 0, 14}, + {16, 0, 18, 0, 0, 14}, + {5, 0, 0, 0, 1, 14}, + {21, 0, 18, 1, 0, 1}, + {22, 0, 18, 1, 0, 0}, + {18, 0, 18, 1, 0, 1}, + {21, 0, 18, 1, 0, 5}, + {7, 0, 0, 1, 33, 14}, + {7, 0, 0, 1, 33, 32}, + {6, 0, 0, 1, 0, 32}, + {6, 0, 0, 1, 0, 5}, + {7, 0, 0, 1, 24, 14}, + {23, 0, 10, 0, 0, 10}, + {26, 0, 18, 0, 0, 14}, + {26, 0, 18, 1, 0, 12}, + {25, 0, 18, 1, 0, 12}, + {1, 0, 18, 5, 0, 21}, + {26, 0, 18, 5, 0, 31}, + {7, 0, 0, 5, 47, 12}, + {14, 0, 18, 5, 2, 12}, + {15, 0, 18, 5, 2, 12}, + {26, 0, 18, 5, 2, 12}, + {26, 0, 0, 5, 2, 12}, + {7, 0, 0, 5, 73, 12}, + {7, 0, 0, 5, 74, 12}, + {7, 0, 0, 5, 37, 12}, + {15, 0, 0, 5, 37, 12}, + {7, 0, 0, 5, 38, 12}, + {14, 0, 0, 5, 38, 12}, + {7, 0, 0, 5, 118, 12}, + {12, 230, 13, 5, 118, 21}, + {7, 0, 0, 5, 48, 12}, + {21, 0, 0, 5, 48, 17}, + {7, 0, 0, 5, 59, 12}, + {21, 0, 0, 5, 59, 17}, + {14, 0, 0, 5, 59, 12}, + {9, 0, 0, 5, 39, 12}, + {5, 0, 0, 5, 39, 12}, + {7, 0, 0, 5, 49, 12}, + {7, 0, 0, 5, 50, 12}, + {13, 0, 0, 5, 50, 11}, + {9, 0, 0, 5, 136, 12}, + {5, 0, 0, 5, 136, 12}, + {7, 0, 0, 5, 106, 12}, + {7, 0, 0, 5, 104, 12}, + {21, 0, 0, 5, 104, 12}, + {7, 0, 0, 5, 110, 12}, + {7, 0, 3, 5, 51, 12}, + {7, 0, 3, 5, 86, 12}, + {21, 0, 3, 5, 86, 17}, + {15, 0, 3, 5, 86, 12}, + {7, 0, 3, 5, 120, 12}, + {26, 0, 3, 5, 120, 12}, + {15, 0, 3, 5, 120, 12}, + {7, 0, 3, 5, 116, 12}, + {15, 0, 3, 5, 116, 12}, + {7, 0, 3, 5, 128, 12}, + {15, 0, 3, 5, 128, 12}, + {7, 0, 3, 5, 63, 12}, + {15, 0, 3, 5, 63, 12}, + {21, 0, 18, 5, 63, 17}, + {7, 0, 3, 5, 75, 12}, + {21, 0, 3, 5, 75, 12}, + {7, 0, 3, 5, 97, 12}, + {7, 0, 3, 5, 96, 12}, + {15, 0, 3, 5, 96, 12}, + {7, 0, 3, 5, 60, 12}, + {12, 0, 13, 5, 60, 21}, + {12, 220, 13, 5, 60, 21}, + {12, 230, 13, 5, 60, 21}, + {12, 1, 13, 5, 60, 21}, + {12, 9, 13, 5, 60, 21}, + {15, 0, 3, 5, 60, 12}, + {21, 0, 3, 5, 60, 17}, + {21, 0, 3, 5, 60, 12}, + {7, 0, 3, 5, 87, 12}, + {15, 0, 3, 5, 87, 12}, + {21, 0, 3, 5, 87, 12}, + {7, 0, 3, 5, 117, 12}, + {15, 0, 3, 5, 117, 12}, + {7, 0, 3, 5, 112, 12}, + {26, 0, 3, 5, 112, 12}, + {12, 230, 13, 5, 112, 21}, + {12, 220, 13, 5, 112, 21}, + {15, 0, 3, 5, 112, 12}, + {21, 0, 3, 5, 112, 17}, + {21, 0, 3, 5, 112, 15}, + {7, 0, 3, 5, 79, 12}, + {21, 0, 18, 5, 79, 17}, + {7, 0, 3, 5, 88, 12}, + {15, 0, 3, 5, 88, 12}, + {7, 0, 3, 5, 89, 12}, + {15, 0, 3, 5, 89, 12}, + {7, 0, 3, 5, 122, 12}, + {21, 0, 3, 5, 122, 12}, + {15, 0, 3, 5, 122, 12}, + {7, 0, 3, 5, 90, 12}, + {9, 0, 3, 5, 130, 12}, + {5, 0, 3, 5, 130, 12}, + {15, 0, 3, 5, 130, 12}, + {15, 0, 11, 5, 6, 12}, + {10, 0, 0, 5, 93, 21}, + {12, 0, 13, 5, 93, 21}, + {7, 0, 0, 5, 93, 12}, + {12, 9, 13, 5, 93, 21}, + {21, 0, 0, 5, 93, 17}, + {21, 0, 0, 5, 93, 12}, + {15, 0, 18, 5, 93, 12}, + {13, 0, 0, 5, 93, 11}, + {12, 0, 13, 5, 91, 21}, + {10, 0, 0, 5, 91, 21}, + {7, 0, 0, 5, 91, 12}, + {12, 9, 13, 5, 91, 21}, + {12, 7, 13, 5, 91, 21}, + {21, 0, 0, 5, 91, 12}, + {1, 0, 0, 5, 91, 12}, + {21, 0, 0, 5, 91, 17}, + {7, 0, 0, 5, 100, 12}, + {13, 0, 0, 5, 100, 11}, + {12, 230, 13, 5, 95, 21}, + {7, 0, 0, 5, 95, 12}, + {12, 0, 13, 5, 95, 21}, + {10, 0, 0, 5, 95, 21}, + {12, 9, 13, 5, 95, 21}, + {13, 0, 0, 5, 95, 11}, + {21, 0, 0, 5, 95, 17}, + {7, 0, 0, 5, 111, 12}, + {12, 7, 13, 5, 111, 21}, + {21, 0, 0, 5, 111, 12}, + {21, 0, 0, 5, 111, 18}, + {12, 0, 13, 5, 99, 21}, + {10, 0, 0, 5, 99, 21}, + {7, 0, 0, 5, 99, 12}, + {10, 9, 0, 5, 99, 21}, + {21, 0, 0, 5, 99, 17}, + {21, 0, 0, 5, 99, 12}, + {12, 7, 13, 5, 99, 21}, + {13, 0, 0, 5, 99, 11}, + {21, 0, 0, 5, 99, 18}, + {15, 0, 0, 5, 18, 12}, + {7, 0, 0, 5, 108, 12}, + {10, 0, 0, 5, 108, 21}, + {12, 0, 13, 5, 108, 21}, + {10, 9, 0, 5, 108, 21}, + {12, 7, 13, 5, 108, 21}, + {21, 0, 0, 5, 108, 17}, + {21, 0, 0, 5, 108, 12}, + {7, 0, 0, 5, 129, 12}, + {21, 0, 0, 5, 129, 17}, + {7, 0, 0, 5, 109, 12}, + {12, 0, 13, 5, 109, 21}, + {10, 0, 0, 5, 109, 21}, + {12, 7, 13, 5, 109, 21}, + {12, 9, 13, 5, 109, 21}, + {13, 0, 0, 5, 109, 11}, + {12, 0, 13, 5, 107, 21}, + {10, 0, 0, 5, 107, 21}, + {7, 0, 0, 5, 107, 12}, + {12, 7, 13, 5, 107, 21}, + {10, 9, 0, 5, 107, 21}, + {12, 230, 13, 5, 107, 21}, + {7, 0, 0, 5, 135, 12}, + {10, 0, 0, 5, 135, 21}, + {12, 0, 13, 5, 135, 21}, + {12, 9, 13, 5, 135, 21}, + {12, 7, 13, 5, 135, 21}, + {21, 0, 0, 5, 135, 17}, + {21, 0, 0, 5, 135, 12}, + {13, 0, 0, 5, 135, 11}, + {7, 0, 0, 5, 124, 12}, + {10, 0, 0, 5, 124, 21}, + {12, 0, 13, 5, 124, 21}, + {12, 9, 13, 5, 124, 21}, + {12, 7, 13, 5, 124, 21}, + {21, 0, 0, 5, 124, 12}, + {13, 0, 0, 5, 124, 11}, + {7, 0, 0, 5, 123, 12}, + {10, 0, 0, 5, 123, 21}, + {12, 0, 13, 5, 123, 21}, + {12, 9, 13, 5, 123, 21}, + {12, 7, 13, 5, 123, 21}, + {21, 0, 0, 5, 123, 18}, + {21, 0, 0, 5, 123, 17}, + {21, 0, 0, 5, 123, 6}, + {21, 0, 0, 5, 123, 12}, + {7, 0, 0, 5, 114, 12}, + {10, 0, 0, 5, 114, 21}, + {12, 0, 13, 5, 114, 21}, + {12, 9, 13, 5, 114, 21}, + {21, 0, 0, 5, 114, 17}, + {21, 0, 0, 5, 114, 12}, + {13, 0, 0, 5, 114, 11}, + {21, 0, 18, 5, 31, 18}, + {7, 0, 0, 5, 101, 12}, + {12, 0, 13, 5, 101, 21}, + {10, 0, 0, 5, 101, 21}, + {10, 9, 0, 5, 101, 21}, + {12, 7, 13, 5, 101, 21}, + {13, 0, 0, 5, 101, 11}, + {7, 0, 0, 5, 126, 36}, + {12, 0, 13, 5, 126, 36}, + {10, 0, 0, 5, 126, 36}, + {12, 9, 13, 5, 126, 36}, + {13, 0, 0, 5, 126, 11}, + {15, 0, 0, 5, 126, 36}, + {21, 0, 0, 5, 126, 17}, + {26, 0, 0, 5, 126, 36}, + {9, 0, 0, 5, 125, 12}, + {5, 0, 0, 5, 125, 12}, + {13, 0, 0, 5, 125, 11}, + {15, 0, 0, 5, 125, 12}, + {7, 0, 0, 5, 125, 12}, + {7, 0, 0, 5, 141, 12}, + {12, 0, 13, 5, 141, 21}, + {10, 0, 0, 5, 141, 21}, + {12, 9, 13, 5, 141, 21}, + {21, 0, 0, 5, 141, 18}, + {21, 0, 0, 5, 141, 12}, + {21, 0, 0, 5, 141, 17}, + {7, 0, 0, 5, 140, 12}, + {12, 0, 13, 5, 140, 21}, + {10, 0, 0, 5, 140, 21}, + {12, 9, 13, 5, 140, 21}, + {21, 0, 0, 5, 140, 17}, + {21, 0, 0, 5, 140, 18}, + {7, 0, 0, 5, 121, 12}, + {7, 0, 0, 5, 133, 12}, + {10, 0, 0, 5, 133, 21}, + {12, 0, 13, 5, 133, 21}, + {12, 9, 0, 5, 133, 21}, + {21, 0, 0, 5, 133, 17}, + {13, 0, 0, 5, 133, 11}, + {15, 0, 0, 5, 133, 12}, + {21, 0, 0, 5, 134, 18}, + {21, 0, 0, 5, 134, 6}, + {7, 0, 0, 5, 134, 12}, + {12, 0, 13, 5, 134, 21}, + {10, 0, 0, 5, 134, 21}, + {7, 0, 0, 5, 138, 12}, + {12, 0, 13, 5, 138, 21}, + {12, 7, 13, 5, 138, 21}, + {12, 9, 13, 5, 138, 21}, + {13, 0, 0, 5, 138, 11}, + {7, 0, 0, 5, 62, 12}, + {14, 0, 0, 5, 62, 12}, + {21, 0, 0, 5, 62, 17}, + {7, 0, 0, 5, 80, 12}, + {7, 0, 0, 5, 80, 0}, + {7, 0, 0, 5, 80, 1}, + {7, 0, 0, 5, 127, 12}, + {7, 0, 0, 5, 127, 0}, + {7, 0, 0, 5, 127, 1}, + {7, 0, 0, 5, 115, 12}, + {13, 0, 0, 5, 115, 11}, + {21, 0, 0, 5, 115, 17}, + {7, 0, 0, 5, 103, 12}, + {12, 1, 13, 5, 103, 21}, + {21, 0, 0, 5, 103, 17}, + {7, 0, 0, 5, 119, 12}, + {12, 230, 13, 5, 119, 21}, + {21, 0, 0, 5, 119, 17}, + {21, 0, 0, 5, 119, 12}, + {26, 0, 0, 5, 119, 12}, + {6, 0, 0, 5, 119, 12}, + {13, 0, 0, 5, 119, 11}, + {15, 0, 0, 5, 119, 12}, + {7, 0, 0, 5, 98, 12}, + {10, 0, 0, 5, 98, 21}, + {12, 0, 13, 5, 98, 21}, + {6, 0, 0, 5, 98, 12}, + {6, 0, 0, 2, 137, 5}, + {6, 0, 0, 2, 139, 5}, + {7, 0, 0, 2, 137, 14}, + {7, 0, 0, 2, 139, 14}, + {7, 0, 0, 5, 105, 12}, + {26, 0, 0, 5, 105, 12}, + {12, 0, 13, 5, 105, 21}, + {12, 1, 13, 5, 105, 21}, + {21, 0, 0, 5, 105, 17}, + {10, 216, 0, 5, 0, 21}, + {10, 226, 0, 5, 0, 21}, + {12, 230, 13, 5, 2, 21}, + {25, 0, 0, 5, 0, 12}, + {13, 0, 8, 5, 0, 11}, + {26, 0, 0, 5, 131, 12}, + {12, 0, 13, 5, 131, 21}, + {21, 0, 0, 5, 131, 17}, + {21, 0, 0, 5, 131, 12}, + {12, 230, 13, 5, 56, 21}, + {7, 0, 3, 5, 113, 12}, + {15, 0, 3, 5, 113, 12}, + {12, 220, 13, 5, 113, 21}, + {9, 0, 3, 5, 132, 12}, + {5, 0, 3, 5, 132, 12}, + {12, 230, 13, 5, 132, 21}, + {12, 7, 13, 5, 132, 21}, + {13, 0, 3, 5, 132, 11}, + {21, 0, 3, 5, 132, 0}, + {2, 0, 18, 5, 102, 14}, + {26, 0, 0, 2, 0, 29}, + {26, 0, 0, 5, 0, 28}, + {26, 0, 0, 2, 32, 14}, + {24, 0, 18, 2, 0, 42}, + {26, 0, 18, 5, 0, 5}, }; #define BIDI_MIRROR_LEN 364 @@ -1893,6 +1906,10 @@ static const Reindex nfc_last[] = { #define UCDN_SCRIPT_NEWA 135 #define UCDN_SCRIPT_OSAGE 136 #define UCDN_SCRIPT_TANGUT 137 +#define UCDN_SCRIPT_MASARAM_GONDI 138 +#define UCDN_SCRIPT_NUSHU 139 +#define UCDN_SCRIPT_SOYOMBO 140 +#define UCDN_SCRIPT_ZANABAZAR_SQUARE 141 #define UCDN_GENERAL_CATEGORY_CC 0 #define UCDN_GENERAL_CATEGORY_CF 1 @@ -1968,21 +1985,21 @@ static const unsigned char index0[] = { 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 52, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 94, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 94, 105, 94, 106, 94, 94, 94, 107, - 107, 107, 108, 109, 110, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 111, - 111, 112, 113, 114, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 115, 116, 117, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 97, 98, 99, 100, 101, 102, 103, 104, 94, 105, 94, 106, 107, 94, 94, 108, + 108, 108, 109, 110, 111, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 112, + 112, 113, 114, 115, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 116, 117, 118, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 118, 118, 119, 120, 94, 94, 94, 121, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 123, 122, 122, 124, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 119, 119, 120, 121, 94, 94, 94, 122, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 124, 123, 123, 125, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 125, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 126, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 135, 136, 94, 94, 94, 94, 94, 137, 94, 94, 94, 94, 94, 94, 94, 138, 139, - 94, 94, 94, 94, 140, 94, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 151, 151, 151, 151, 152, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 126, 127, 128, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 129, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 138, 139, 94, 94, 94, 94, 94, 140, 94, 94, 94, 94, 94, 94, 94, 141, + 142, 94, 94, 94, 94, 143, 94, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 154, 154, 154, 154, 155, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, @@ -1991,31 +2008,31 @@ static const unsigned char index0[] = { 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 153, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 154, 155, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 156, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 52, 52, - 158, 157, 157, 157, 157, 159, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 157, 157, 159, 94, 94, 94, 94, 94, 94, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 156, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 157, 158, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 159, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 160, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 52, 52, 162, 161, 161, 161, 161, 163, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 163, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, @@ -2157,7 +2174,7 @@ static const unsigned char index0[] = { 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 160, 161, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 164, 165, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, @@ -2171,8 +2188,7 @@ static const unsigned char index0[] = { 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 94, 94, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, @@ -2186,7 +2202,7 @@ static const unsigned char index0[] = { 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 162, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 166, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, @@ -2200,7 +2216,8 @@ static const unsigned char index0[] = { 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 74, 162, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 166, }; static const unsigned short index1[] = { @@ -2220,1136 +2237,1145 @@ static const unsigned short index1[] = { 128, 128, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 145, 145, 146, 147, 148, 149, 128, 128, 128, 128, 128, 128, 150, 150, 150, 150, 151, 152, 153, 120, 154, 155, 156, 156, 156, 157, 158, 159, 160, 160, - 161, 162, 163, 164, 165, 166, 167, 167, 167, 168, 120, 120, 120, 120, - 120, 120, 120, 120, 128, 128, 169, 170, 120, 120, 171, 126, 172, 173, - 174, 175, 176, 177, 177, 177, 177, 177, 177, 178, 179, 180, 181, 177, - 182, 183, 184, 177, 185, 186, 187, 188, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 120, 214, 215, 216, 217, 217, 218, - 219, 220, 221, 222, 223, 120, 224, 225, 226, 227, 228, 229, 230, 231, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 120, 242, 243, - 244, 245, 246, 243, 247, 248, 249, 250, 251, 120, 252, 253, 254, 255, - 256, 257, 258, 259, 259, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 120, 267, 268, 269, 270, 271, 271, 270, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 120, 281, 282, 283, 284, 284, 284, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 295, 295, 298, 299, - 296, 300, 301, 302, 303, 304, 305, 120, 306, 307, 307, 307, 307, 307, - 308, 309, 310, 311, 312, 313, 120, 120, 120, 120, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 120, 120, 120, 120, 326, 327, - 328, 329, 330, 331, 332, 333, 334, 335, 334, 334, 334, 336, 337, 338, - 339, 340, 341, 342, 341, 341, 341, 343, 344, 345, 346, 347, 120, 120, - 120, 120, 348, 348, 348, 348, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 348, 359, 360, 352, 361, 362, 362, 362, 362, 363, 364, - 365, 365, 365, 365, 365, 366, 367, 367, 367, 367, 367, 367, 367, 367, - 367, 367, 367, 367, 368, 368, 368, 368, 368, 368, 368, 368, 368, 369, - 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 370, 370, 370, 370, - 370, 370, 370, 370, 370, 371, 372, 371, 370, 370, 370, 370, 370, 371, - 370, 370, 370, 370, 371, 372, 371, 370, 372, 370, 370, 370, 370, 370, - 370, 370, 371, 370, 370, 370, 370, 370, 370, 370, 370, 373, 374, 375, - 376, 377, 370, 370, 378, 379, 380, 380, 380, 380, 380, 380, 380, 380, - 380, 380, 381, 382, 383, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, - 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 384, 384, - 386, 387, 387, 388, 389, 389, 389, 389, 389, 389, 389, 389, 389, 390, - 391, 392, 393, 394, 395, 120, 396, 396, 397, 120, 398, 398, 399, 120, - 400, 401, 402, 120, 403, 403, 403, 403, 403, 403, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 418, 418, 418, - 419, 418, 418, 418, 418, 418, 418, 120, 420, 418, 418, 418, 418, 421, - 384, 384, 384, 384, 384, 384, 384, 384, 422, 120, 423, 423, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 431, 431, 432, 433, 120, 434, 434, - 434, 434, 434, 435, 434, 434, 434, 436, 437, 438, 439, 439, 439, 439, - 440, 440, 441, 442, 443, 443, 443, 443, 443, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 450, 451, 452, 453, 454, 455, 120, 120, 120, 120, - 120, 120, 120, 120, 456, 457, 457, 457, 457, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 469, 469, 470, 471, 472, 473, - 474, 474, 474, 474, 475, 476, 477, 478, 479, 479, 479, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 488, 488, 489, 100, 490, 120, 120, - 120, 120, 120, 120, 491, 120, 492, 493, 494, 495, 496, 497, 54, 54, 54, - 54, 498, 499, 56, 56, 56, 56, 56, 500, 501, 502, 54, 503, 54, 54, 54, - 504, 56, 56, 56, 505, 506, 507, 508, 509, 509, 509, 510, 511, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 512, 513, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 514, 515, 516, 517, 514, 515, - 514, 515, 516, 517, 514, 518, 514, 515, 514, 516, 514, 519, 514, 519, - 514, 519, 520, 521, 522, 523, 524, 525, 514, 526, 527, 528, 529, 530, - 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, - 545, 546, 56, 547, 548, 549, 550, 551, 552, 552, 553, 554, 555, 556, 557, - 120, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, - 571, 570, 572, 573, 574, 575, 576, 577, 578, 579, 580, 579, 581, 582, - 579, 583, 579, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, - 595, 596, 597, 598, 599, 594, 594, 600, 601, 602, 603, 604, 594, 594, - 605, 585, 606, 607, 594, 594, 608, 594, 594, 579, 609, 610, 611, 612, - 613, 614, 615, 615, 615, 615, 615, 615, 615, 615, 616, 579, 579, 617, - 618, 585, 585, 619, 579, 579, 579, 579, 584, 620, 621, 622, 623, 579, - 579, 579, 579, 623, 120, 120, 120, 579, 624, 120, 120, 625, 625, 625, - 625, 625, 626, 626, 627, 628, 628, 628, 628, 628, 628, 628, 628, 628, - 629, 625, 630, 631, 631, 631, 631, 631, 631, 631, 631, 631, 632, 631, - 631, 631, 631, 633, 579, 631, 631, 634, 579, 635, 636, 637, 638, 639, - 640, 636, 579, 634, 641, 579, 642, 643, 644, 645, 646, 579, 579, 579, - 647, 648, 649, 650, 579, 651, 652, 579, 653, 579, 579, 654, 655, 656, - 657, 579, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 579, - 579, 579, 669, 579, 670, 579, 671, 672, 673, 674, 675, 676, 625, 677, - 677, 678, 579, 579, 579, 669, 679, 680, 681, 682, 683, 684, 685, 585, - 585, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, - 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, - 686, 686, 686, 686, 686, 585, 585, 585, 585, 585, 585, 585, 585, 585, - 585, 585, 585, 585, 585, 585, 585, 687, 688, 688, 689, 594, 594, 585, - 690, 691, 692, 693, 694, 695, 696, 697, 698, 585, 699, 594, 700, 701, - 702, 703, 683, 585, 585, 597, 690, 703, 704, 705, 706, 594, 594, 594, - 594, 707, 708, 594, 594, 594, 594, 709, 710, 711, 683, 712, 713, 579, - 579, 579, 714, 579, 579, 585, 585, 715, 716, 717, 636, 579, 579, 718, - 579, 579, 579, 719, 579, 579, 579, 579, 720, 579, 721, 722, 120, 120, - 723, 120, 120, 724, 724, 724, 724, 724, 725, 726, 726, 726, 726, 726, - 727, 728, 729, 730, 731, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 732, 733, 734, 735, 736, 736, 736, 736, 737, 738, 739, 739, 739, 739, - 739, 739, 739, 740, 741, 742, 370, 370, 372, 120, 372, 372, 372, 372, - 372, 372, 372, 372, 743, 743, 743, 743, 744, 745, 746, 747, 748, 749, - 750, 751, 752, 120, 120, 120, 120, 120, 120, 120, 753, 753, 753, 754, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 755, 120, 753, 753, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 756, 120, 120, 120, - 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 769, - 770, 769, 769, 769, 771, 772, 773, 774, 775, 776, 777, 777, 778, 777, - 777, 777, 779, 780, 781, 782, 783, 784, 784, 784, 784, 785, 786, 787, - 787, 787, 787, 787, 787, 787, 787, 787, 787, 788, 789, 790, 784, 784, - 784, 791, 757, 757, 757, 757, 758, 120, 792, 792, 793, 793, 793, 794, - 795, 796, 790, 790, 790, 797, 798, 799, 793, 793, 793, 800, 795, 796, - 790, 790, 790, 790, 801, 799, 790, 802, 803, 803, 803, 803, 803, 804, - 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 790, 790, 790, - 805, 806, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 807, - 790, 790, 790, 805, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 809, 810, 579, 579, 579, 579, 579, 579, 579, 579, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 809, 810, 810, 810, - 810, 810, 811, 811, 812, 811, 811, 811, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, - 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 813, - 814, 814, 814, 814, 814, 814, 815, 120, 816, 816, 816, 816, 816, 817, - 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, - 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, - 818, 818, 818, 818, 818, 819, 818, 818, 820, 821, 120, 120, 101, 101, - 101, 101, 101, 822, 823, 824, 101, 101, 101, 825, 826, 826, 826, 826, - 826, 826, 826, 826, 827, 828, 829, 120, 64, 64, 830, 831, 832, 27, 833, - 27, 27, 27, 27, 27, 27, 27, 834, 835, 27, 836, 837, 27, 27, 838, 839, - 120, 120, 120, 120, 120, 120, 120, 840, 841, 842, 843, 844, 844, 845, - 846, 847, 848, 849, 849, 849, 849, 849, 849, 850, 120, 851, 852, 852, - 852, 852, 852, 853, 854, 855, 856, 857, 858, 859, 859, 860, 861, 862, - 863, 864, 864, 865, 866, 867, 867, 868, 869, 870, 871, 367, 367, 367, - 872, 873, 874, 874, 874, 874, 874, 875, 876, 877, 878, 879, 880, 881, - 348, 352, 882, 883, 883, 883, 883, 883, 884, 885, 120, 886, 887, 888, - 889, 348, 348, 890, 891, 892, 892, 892, 892, 892, 892, 893, 894, 895, - 120, 120, 896, 897, 898, 899, 120, 900, 900, 900, 120, 372, 372, 54, 54, - 54, 54, 54, 901, 902, 120, 903, 903, 903, 903, 903, 903, 903, 903, 903, - 903, 897, 897, 897, 897, 904, 905, 906, 907, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, - 909, 909, 908, 909, 909, 910, 909, 909, 909, 909, 909, 909, 908, 909, - 909, 910, 909, 909, 909, 908, 909, 909, 910, 909, 909, 909, 908, 909, - 909, 911, 120, 368, 368, 912, 913, 369, 369, 369, 369, 369, 914, 915, - 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, - 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, - 915, 915, 915, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, - 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, - 916, 916, 916, 916, 916, 916, 916, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 809, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 917, 810, 810, 810, 810, 918, 120, 919, - 920, 121, 921, 922, 923, 924, 121, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 925, 926, 927, 120, 928, 128, 128, 128, 128, + 161, 162, 163, 164, 165, 166, 167, 167, 167, 168, 145, 169, 120, 120, + 120, 120, 120, 120, 128, 128, 170, 171, 120, 120, 172, 126, 173, 174, + 175, 176, 177, 178, 178, 178, 178, 178, 178, 179, 180, 181, 182, 178, + 183, 184, 185, 178, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 120, 215, 216, 217, 218, 218, 219, + 220, 221, 222, 223, 224, 120, 225, 226, 227, 228, 229, 230, 231, 232, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 120, 243, 244, + 245, 246, 247, 244, 248, 249, 250, 251, 252, 120, 253, 254, 255, 256, + 257, 258, 259, 260, 260, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 120, 268, 269, 270, 271, 272, 272, 271, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 120, 282, 283, 284, 285, 285, 285, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 296, 296, 299, 300, + 297, 301, 302, 303, 304, 305, 306, 120, 307, 308, 308, 308, 308, 308, + 309, 310, 311, 312, 313, 314, 120, 120, 120, 120, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 120, 120, 120, 120, 327, 328, + 329, 330, 331, 332, 333, 334, 335, 336, 335, 335, 335, 337, 338, 339, + 340, 341, 342, 343, 342, 342, 342, 344, 345, 346, 347, 348, 120, 120, + 120, 120, 349, 349, 349, 349, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 349, 360, 361, 353, 362, 363, 363, 363, 363, 364, 365, + 366, 366, 366, 366, 366, 367, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, 369, 369, 369, 370, + 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 371, 371, 371, 371, + 371, 371, 371, 371, 371, 372, 373, 372, 371, 371, 371, 371, 371, 372, + 371, 371, 371, 371, 372, 373, 372, 371, 373, 371, 371, 371, 371, 371, + 371, 371, 372, 371, 371, 371, 371, 371, 371, 371, 371, 374, 375, 376, + 377, 378, 371, 371, 379, 380, 381, 381, 381, 381, 381, 381, 381, 381, + 381, 381, 382, 383, 384, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, + 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 386, 385, 385, + 387, 388, 388, 389, 390, 390, 390, 390, 390, 390, 390, 390, 390, 391, + 392, 393, 394, 395, 396, 120, 397, 397, 398, 120, 399, 399, 400, 120, + 401, 402, 403, 120, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 419, 419, 419, + 420, 419, 419, 419, 419, 419, 419, 120, 421, 419, 419, 419, 419, 422, + 385, 385, 385, 385, 385, 385, 385, 385, 423, 120, 424, 424, 424, 425, + 426, 427, 428, 429, 430, 431, 432, 432, 432, 433, 434, 120, 435, 435, + 435, 435, 435, 436, 435, 435, 435, 437, 438, 439, 440, 440, 440, 440, + 441, 441, 442, 443, 444, 444, 444, 444, 444, 444, 445, 446, 447, 448, + 449, 450, 451, 452, 451, 452, 453, 454, 455, 456, 120, 120, 120, 120, + 120, 120, 120, 120, 457, 458, 458, 458, 458, 458, 459, 460, 461, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 470, 470, 471, 472, 473, 474, + 475, 475, 475, 475, 476, 477, 478, 479, 480, 480, 480, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 489, 489, 490, 100, 491, 120, 120, + 120, 120, 120, 120, 492, 120, 493, 494, 495, 496, 497, 498, 54, 54, 54, + 54, 499, 500, 56, 56, 56, 56, 56, 501, 502, 503, 54, 504, 54, 54, 54, + 505, 56, 56, 56, 506, 507, 508, 509, 510, 510, 510, 511, 512, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 513, 514, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 515, 516, 517, 518, 515, 516, + 515, 516, 517, 518, 515, 519, 515, 516, 515, 517, 515, 520, 515, 520, + 515, 520, 521, 522, 523, 524, 525, 526, 515, 527, 528, 529, 530, 531, + 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, + 546, 547, 56, 548, 549, 550, 551, 552, 553, 553, 554, 555, 556, 557, 558, + 120, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, + 572, 571, 573, 574, 575, 576, 577, 578, 579, 580, 581, 580, 582, 583, + 580, 584, 580, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 586, + 595, 596, 586, 597, 598, 586, 586, 598, 586, 599, 600, 599, 586, 586, + 601, 586, 586, 586, 586, 586, 602, 586, 586, 580, 603, 604, 605, 606, + 607, 608, 609, 609, 609, 609, 609, 609, 609, 609, 610, 580, 580, 611, + 612, 586, 586, 613, 580, 580, 580, 580, 585, 606, 614, 615, 580, 580, + 580, 580, 580, 616, 120, 120, 120, 580, 617, 120, 120, 618, 618, 618, + 618, 618, 619, 619, 620, 621, 621, 621, 621, 621, 621, 621, 621, 621, + 622, 618, 623, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625, 624, + 624, 624, 624, 626, 580, 624, 624, 627, 580, 628, 629, 630, 631, 632, + 633, 629, 580, 627, 634, 580, 635, 636, 637, 638, 639, 580, 580, 580, + 640, 641, 642, 643, 580, 644, 645, 580, 646, 580, 580, 647, 648, 649, + 650, 580, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 580, + 580, 580, 662, 580, 663, 580, 664, 665, 666, 667, 668, 669, 618, 670, + 670, 671, 580, 580, 580, 662, 672, 673, 586, 586, 586, 674, 675, 586, + 586, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, + 676, 676, 676, 676, 676, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 677, 678, 678, 679, 586, 586, 586, + 586, 586, 586, 586, 680, 586, 586, 586, 681, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 580, + 580, 580, 682, 580, 580, 586, 586, 683, 684, 685, 629, 580, 580, 686, + 580, 580, 580, 687, 580, 580, 580, 580, 688, 580, 689, 617, 120, 120, + 690, 120, 120, 691, 691, 691, 691, 691, 692, 693, 693, 693, 693, 693, + 694, 695, 696, 697, 698, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 699, 700, 701, 702, 703, 703, 703, 703, 704, 705, 706, 706, 706, 706, + 706, 706, 706, 707, 708, 709, 371, 371, 373, 120, 373, 373, 373, 373, + 373, 373, 373, 373, 710, 710, 710, 710, 711, 712, 713, 714, 715, 716, + 717, 718, 719, 720, 120, 120, 120, 120, 120, 120, 721, 721, 721, 722, + 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 723, 120, 721, 721, + 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, + 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 724, 120, 120, 120, + 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 737, + 738, 737, 737, 737, 739, 740, 741, 742, 743, 744, 745, 745, 746, 745, + 745, 745, 747, 748, 749, 750, 751, 752, 752, 752, 752, 753, 754, 755, + 755, 755, 755, 755, 755, 755, 755, 755, 755, 756, 757, 758, 752, 752, + 752, 759, 725, 725, 725, 725, 726, 120, 760, 760, 761, 761, 761, 762, + 763, 764, 758, 758, 758, 765, 766, 767, 761, 761, 761, 768, 763, 764, + 758, 758, 758, 758, 769, 767, 758, 770, 771, 771, 771, 771, 771, 772, + 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 758, 758, 758, + 773, 774, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 775, + 758, 758, 758, 773, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 777, 778, 580, 580, 580, 580, 580, 580, 580, 580, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 779, + 778, 778, 780, 780, 781, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 782, + 783, 783, 783, 783, 783, 783, 784, 120, 785, 785, 785, 785, 785, 786, + 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 788, 787, 787, 789, 790, 120, 120, 101, 101, + 101, 101, 101, 791, 792, 793, 101, 101, 101, 794, 795, 795, 795, 795, + 795, 795, 795, 795, 796, 797, 798, 120, 64, 64, 799, 800, 801, 27, 802, + 27, 27, 27, 27, 27, 27, 27, 803, 804, 27, 805, 806, 27, 27, 807, 808, + 120, 120, 120, 120, 120, 120, 120, 809, 810, 811, 812, 813, 813, 814, + 815, 816, 817, 818, 818, 818, 818, 818, 818, 819, 120, 820, 821, 821, + 821, 821, 821, 822, 823, 824, 825, 826, 827, 828, 828, 829, 830, 831, + 832, 833, 833, 834, 835, 836, 836, 837, 838, 839, 840, 368, 368, 368, + 841, 842, 843, 843, 843, 843, 843, 844, 845, 846, 847, 848, 849, 850, + 349, 353, 851, 852, 852, 852, 852, 852, 853, 854, 120, 855, 856, 857, + 858, 349, 349, 859, 860, 861, 861, 861, 861, 861, 861, 862, 863, 864, + 120, 120, 865, 866, 867, 868, 120, 869, 869, 869, 120, 373, 373, 54, 54, + 54, 54, 54, 870, 871, 120, 872, 872, 872, 872, 872, 872, 872, 872, 872, + 872, 866, 866, 866, 866, 873, 874, 875, 876, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, + 878, 878, 877, 878, 878, 879, 878, 878, 878, 878, 878, 878, 877, 878, + 878, 879, 878, 878, 878, 877, 878, 878, 879, 878, 878, 878, 877, 878, + 878, 880, 120, 369, 369, 881, 882, 370, 370, 370, 370, 370, 883, 884, + 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, + 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, + 884, 884, 884, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, + 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, + 885, 885, 885, 885, 885, 885, 885, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 777, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 886, 778, 778, 778, 778, 887, 120, 888, + 889, 121, 890, 891, 892, 893, 121, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 894, 895, 896, 120, 897, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 929, 120, - 120, 128, 128, 128, 128, 128, 128, 128, 128, 930, 128, 128, 128, 128, - 128, 128, 120, 120, 120, 120, 120, 128, 931, 932, 932, 933, 934, 935, - 936, 937, 938, 939, 940, 941, 942, 943, 944, 169, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 945, 946, - 947, 948, 949, 950, 951, 951, 952, 953, 954, 954, 955, 956, 957, 958, - 959, 959, 959, 959, 960, 961, 961, 961, 962, 963, 963, 963, 964, 965, - 966, 120, 967, 968, 969, 968, 968, 970, 968, 968, 971, 968, 972, 968, - 972, 120, 120, 120, 120, 968, 968, 968, 968, 968, 968, 968, 968, 968, - 968, 968, 968, 968, 968, 968, 973, 974, 975, 975, 975, 975, 975, 976, - 615, 977, 977, 977, 977, 977, 977, 978, 979, 980, 981, 579, 982, 983, - 120, 120, 120, 120, 120, 615, 615, 615, 615, 615, 984, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 985, - 985, 985, 986, 987, 987, 987, 987, 987, 987, 988, 120, 989, 990, 990, - 991, 992, 992, 992, 992, 993, 120, 994, 994, 995, 996, 997, 997, 997, - 997, 998, 999, 1000, 1000, 1000, 1001, 1002, 1002, 1002, 1002, 1003, - 1002, 1004, 120, 120, 120, 120, 120, 1005, 1005, 1005, 1005, 1005, 1006, - 1006, 1006, 1006, 1006, 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008, - 1008, 1009, 1010, 1011, 1012, 1012, 1012, 1012, 1013, 1014, 1014, 1014, - 1014, 1015, 1016, 1016, 1016, 1016, 1016, 120, 1017, 1017, 1017, 1017, - 1017, 1017, 1018, 1019, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 1020, 1020, 1020, 1020, 1020, - 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, - 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, - 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1021, 120, 1020, - 1020, 1022, 120, 1020, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 1023, 1024, 1025, 1025, - 1025, 1025, 1026, 1027, 1028, 1028, 1029, 1030, 1031, 1031, 1032, 1033, - 1034, 1034, 1034, 1035, 1036, 1037, 120, 120, 120, 120, 120, 120, 1038, - 1038, 1039, 1040, 1041, 1041, 1042, 1043, 1044, 1044, 1044, 1045, 120, - 120, 120, 120, 120, 120, 120, 120, 1046, 1046, 1046, 1046, 1047, 1047, - 1047, 1048, 1049, 1049, 1050, 1049, 1049, 1049, 1049, 1049, 1051, 1052, - 1053, 1054, 1055, 1055, 1056, 1057, 1058, 120, 1059, 1060, 1061, 1061, - 1061, 1062, 1063, 1063, 1063, 1064, 120, 120, 120, 120, 1065, 1066, 1065, - 1065, 1067, 1068, 1069, 120, 1070, 1070, 1070, 1070, 1070, 1070, 1071, - 1072, 1073, 1073, 1074, 1075, 1076, 1076, 1077, 1078, 1079, 1079, 1080, - 1081, 120, 1082, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1083, - 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1084, 120, 120, 120, 120, - 120, 120, 1085, 1085, 1085, 1085, 1085, 1085, 1086, 120, 1087, 1087, - 1087, 1087, 1087, 1087, 1088, 1089, 120, 120, 120, 120, 120, 120, 120, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 898, 120, + 120, 128, 128, 128, 128, 128, 128, 128, 128, 899, 128, 128, 128, 128, + 128, 128, 120, 120, 120, 120, 120, 128, 900, 901, 901, 902, 903, 904, + 905, 906, 907, 908, 909, 910, 911, 912, 913, 170, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 914, 915, + 916, 917, 918, 919, 920, 920, 921, 922, 923, 923, 924, 925, 926, 927, + 928, 928, 928, 928, 929, 930, 930, 930, 931, 932, 932, 932, 933, 934, + 935, 120, 936, 937, 938, 937, 937, 939, 937, 937, 940, 937, 941, 937, + 941, 120, 120, 120, 120, 937, 937, 937, 937, 937, 937, 937, 937, 937, + 937, 937, 937, 937, 937, 937, 942, 943, 944, 944, 944, 944, 944, 945, + 609, 946, 946, 946, 946, 946, 946, 947, 948, 949, 950, 580, 951, 952, + 120, 120, 120, 120, 120, 609, 609, 609, 609, 609, 953, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 954, + 954, 954, 955, 956, 956, 956, 956, 956, 956, 957, 120, 958, 959, 959, + 960, 961, 961, 961, 961, 962, 963, 964, 964, 965, 966, 967, 967, 967, + 967, 968, 969, 970, 970, 970, 971, 972, 972, 972, 972, 973, 972, 974, + 120, 120, 120, 120, 120, 975, 975, 975, 975, 975, 976, 976, 976, 976, + 976, 977, 977, 977, 977, 977, 977, 978, 978, 978, 979, 980, 981, 982, + 982, 982, 982, 983, 984, 984, 984, 984, 985, 986, 986, 986, 986, 986, + 120, 987, 987, 987, 987, 987, 987, 988, 989, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 990, + 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, + 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, + 990, 990, 990, 990, 990, 990, 990, 990, 990, 991, 120, 990, 990, 992, + 120, 990, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 993, 994, 995, 995, 995, 995, 996, + 997, 998, 998, 999, 1000, 1001, 1001, 1002, 1003, 1004, 1004, 1004, 1005, + 1006, 1007, 120, 120, 120, 120, 120, 120, 1008, 1008, 1009, 1010, 1011, + 1011, 1012, 1013, 1014, 1014, 1014, 1015, 120, 120, 120, 120, 120, 120, + 120, 120, 1016, 1016, 1016, 1016, 1017, 1017, 1017, 1018, 1019, 1019, + 1020, 1019, 1019, 1019, 1019, 1019, 1021, 1022, 1023, 1024, 1025, 1025, + 1026, 1027, 1028, 120, 1029, 1030, 1031, 1031, 1031, 1032, 1033, 1033, + 1033, 1034, 120, 120, 120, 120, 1035, 1036, 1035, 1035, 1037, 1038, 1039, + 120, 1040, 1040, 1040, 1040, 1040, 1040, 1041, 1042, 1043, 1043, 1044, + 1045, 1046, 1046, 1047, 1048, 1049, 1049, 1050, 1051, 120, 1052, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 1053, 1053, 1053, 1053, + 1053, 1053, 1053, 1053, 1053, 1054, 120, 120, 120, 120, 120, 120, 1055, + 1055, 1055, 1055, 1055, 1055, 1056, 120, 1057, 1057, 1057, 1057, 1057, + 1057, 1058, 1059, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 1090, 1090, 1090, 1091, 120, + 120, 120, 120, 120, 120, 1060, 1060, 1060, 1061, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1062, 1063, 1063, + 1063, 1063, 1063, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 120, + 1071, 1072, 1073, 1073, 1073, 1073, 1073, 1074, 1075, 1076, 120, 1077, + 1077, 1077, 1078, 1079, 1080, 1081, 1082, 1082, 1082, 1083, 1084, 1085, + 1086, 1087, 120, 1088, 1088, 1088, 1088, 1089, 120, 1090, 1091, 1091, + 1091, 1091, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, + 120, 1101, 1101, 1102, 1101, 1101, 1103, 1104, 1105, 120, 120, 120, 120, + 120, 120, 120, 120, 1106, 1107, 1108, 1109, 1108, 1110, 1111, 1111, 1111, + 1111, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1120, + 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1129, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 1092, 1093, 1093, 1093, 1093, 1093, 1093, 1094, 1095, 1096, 1097, - 1098, 1099, 1100, 120, 1101, 1102, 1103, 1103, 1103, 1103, 1103, 1104, - 1105, 1106, 120, 1107, 1107, 1107, 1108, 1109, 1110, 1111, 1112, 1112, - 1112, 1113, 1114, 1115, 1116, 1117, 120, 1118, 1118, 1118, 1118, 1119, - 120, 1120, 1121, 1121, 1121, 1121, 1121, 1122, 1123, 1124, 1125, 1126, - 1127, 1128, 1129, 1130, 120, 1131, 1131, 1132, 1131, 1131, 1133, 1134, - 1135, 120, 120, 120, 120, 120, 120, 120, 120, 1136, 1137, 1138, 1139, - 1138, 1140, 1141, 1141, 1141, 1141, 1141, 1142, 1143, 1144, 1145, 1146, - 1147, 1148, 1149, 1150, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, - 1158, 1159, 1159, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 1160, 1160, 1160, 1160, 1160, 1160, 1161, - 1162, 1163, 1164, 1165, 1166, 120, 120, 120, 120, 1167, 1167, 1167, 1167, - 1167, 1167, 1168, 1169, 1170, 120, 1171, 1172, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 1173, 1173, 1173, 1173, 1173, 1174, 1175, 1176, 1177, 1178, 1179, - 1180, 120, 120, 120, 120, 1181, 1181, 1181, 1181, 1181, 1181, 1182, 1183, - 1184, 120, 1185, 1186, 1187, 1188, 120, 120, 1189, 1189, 1189, 1189, - 1189, 1190, 1191, 120, 1192, 1193, 120, 120, 120, 120, 120, 120, 1194, - 1194, 1194, 1195, 1196, 1197, 1198, 1199, 120, 120, 120, 120, 120, 120, + 120, 1130, 1130, 1130, 1130, 1130, 1130, 1131, 1132, 1133, 1134, 1135, + 1136, 120, 120, 120, 120, 1137, 1137, 1137, 1137, 1137, 1137, 1138, 1139, + 1140, 120, 1141, 1142, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1143, 1143, 1143, 1143, + 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 120, 120, 120, 120, 1151, + 1151, 1151, 1151, 1151, 1151, 1152, 1153, 1154, 120, 1155, 1156, 1157, + 1158, 120, 120, 1159, 1159, 1159, 1159, 1159, 1160, 1161, 120, 1162, + 1163, 120, 120, 120, 120, 120, 120, 1164, 1164, 1164, 1165, 1166, 1167, + 1168, 1169, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1200, 1200, 1200, 1200, - 1201, 1201, 1201, 1201, 1202, 1203, 1204, 1205, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 1170, 1170, 1170, 1170, 1171, 1171, 1171, 1171, 1172, + 1173, 1174, 1175, 1176, 1177, 1178, 1178, 1178, 1178, 1179, 1180, 1181, + 120, 1182, 1183, 1184, 1184, 1184, 1184, 1185, 1186, 1187, 1188, 1189, + 120, 120, 120, 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1191, 1192, + 1193, 1192, 1192, 1192, 1194, 1195, 1196, 1197, 120, 1198, 1199, 1200, + 1201, 1202, 1203, 1203, 1203, 1204, 1205, 1205, 1206, 1207, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 1208, 1209, 1210, 1210, 1210, 1210, + 1211, 1212, 1213, 120, 1214, 1215, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1216, + 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1217, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, + 1218, 1218, 1219, 1220, 120, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, + 1216, 1216, 1216, 1216, 1216, 1221, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1207, - 1208, 1209, 1208, 1208, 1208, 1210, 1211, 1212, 1213, 120, 1214, 1215, - 1216, 1217, 1218, 1219, 1219, 1219, 1220, 1221, 1221, 1222, 1223, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1225, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1226, 1226, 1226, - 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1226, 1227, 1228, - 120, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, 1224, - 1224, 1229, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1231, 1230, 1230, 1230, 1230, 1232, 1233, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1234, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - 1230, 1230, 1235, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1223, 1222, 1222, + 1222, 1222, 1224, 1225, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1226, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, + 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1227, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1237, 1236, - 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, - 1236, 1238, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 826, 826, 826, - 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, - 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, - 826, 826, 826, 826, 826, 826, 826, 826, 1239, 1240, 1240, 1240, 1241, - 1242, 1243, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 1244, 1244, 1244, 1245, 1246, 120, 1247, 1247, 1247, 1247, 1247, 1247, - 1248, 1249, 1250, 120, 1251, 1252, 1253, 1247, 1247, 1254, 1247, 1247, + 120, 120, 120, 120, 120, 120, 120, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1229, 1228, 1228, 1228, 1228, 1228, 1228, 1228, 1228, + 1228, 1228, 1228, 1228, 1228, 1228, 1230, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1255, 1256, 120, 1257, 1258, - 1258, 1258, 1258, 1259, 120, 1260, 1261, 1262, 120, 120, 120, 120, 120, - 120, 120, 120, 1263, 120, 120, 120, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1265, 120, 120, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, 1264, - 1264, 1264, 1264, 1264, 1266, 120, 1267, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, + 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, + 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, + 1231, 1232, 1232, 1232, 1233, 1234, 1235, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 1236, 1236, 1236, 1237, 1238, 120, 1239, + 1239, 1239, 1239, 1239, 1239, 1240, 1241, 1242, 120, 1243, 1244, 1245, + 1239, 1239, 1246, 1239, 1239, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 1247, 1247, 1247, 1247, 1247, 1247, 1247, + 1247, 1248, 120, 1249, 1250, 1250, 1250, 1250, 1251, 120, 1252, 1253, + 1254, 120, 120, 120, 120, 120, 120, 120, 120, 1255, 120, 120, 120, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1257, 120, 120, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1258, 120, 1259, + 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, 737, + 737, 737, 737, 737, 737, 737, 1260, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, + 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, + 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, + 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, 1261, + 1261, 1261, 1261, 1261, 1262, 1263, 1263, 1263, 1263, 1263, 1263, 1263, + 1263, 1263, 1263, 1263, 1263, 1263, 1264, 1263, 1265, 1263, 1266, 1263, + 1267, 1268, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 609, + 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, + 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, + 609, 1269, 120, 609, 609, 609, 609, 1270, 1271, 609, 609, 609, 609, 609, + 609, 1272, 1273, 1274, 1275, 1276, 1277, 609, 609, 609, 1278, 609, 609, + 609, 609, 609, 609, 609, 1279, 120, 120, 949, 949, 949, 949, 949, 949, + 949, 949, 1280, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 580, 580, + 580, 580, 580, 580, 580, 580, 580, 580, 616, 120, 944, 944, 1281, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1268, 1268, 1268, - 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1269, 1268, - 1270, 1268, 1271, 1268, 1272, 1273, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 615, 1274, 120, 615, 615, 615, 615, 1275, 1276, - 615, 615, 615, 615, 615, 615, 1277, 1278, 1279, 1280, 1281, 1282, 615, - 615, 615, 1283, 615, 615, 615, 615, 615, 615, 615, 1284, 120, 120, 980, - 980, 980, 980, 980, 980, 980, 980, 1285, 120, 120, 120, 120, 120, 120, + 120, 120, 1282, 1282, 1282, 1283, 1284, 1284, 1285, 1282, 1282, 1286, + 1287, 1284, 1284, 1282, 1282, 1282, 1283, 1284, 1284, 1288, 1289, 1290, + 1286, 1291, 1292, 1284, 1282, 1282, 1282, 1283, 1284, 1284, 1293, 1294, + 1295, 1296, 1284, 1284, 1284, 1297, 1298, 1299, 1300, 1284, 1284, 1285, + 1282, 1282, 1286, 1284, 1284, 1284, 1282, 1282, 1282, 1283, 1284, 1284, + 1285, 1282, 1282, 1286, 1284, 1284, 1284, 1282, 1282, 1282, 1283, 1284, + 1284, 1285, 1282, 1282, 1286, 1284, 1284, 1284, 1282, 1282, 1282, 1283, + 1284, 1284, 1301, 1282, 1282, 1282, 1302, 1284, 1284, 1303, 1304, 1282, + 1282, 1305, 1284, 1284, 1306, 1285, 1282, 1282, 1307, 1284, 1284, 1308, + 1309, 1282, 1282, 1310, 1284, 1284, 1284, 1311, 1282, 1282, 1282, 1302, + 1284, 1284, 1303, 1312, 1313, 1313, 1313, 1313, 1313, 1313, 1314, 1314, + 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, + 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, + 1314, 1314, 1314, 1314, 1314, 1314, 1315, 1315, 1315, 1315, 1315, 1315, + 1316, 1317, 1315, 1315, 1315, 1315, 1315, 1318, 1319, 1314, 1320, 1321, + 120, 1322, 1323, 1315, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, + 1324, 1325, 1325, 1326, 1327, 1328, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 623, - 120, 975, 975, 1286, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 1287, 1287, 1287, 1288, 1289, 1289, - 1290, 1287, 1287, 1291, 1292, 1289, 1289, 1287, 1287, 1287, 1288, 1289, - 1289, 1293, 1294, 1295, 1291, 1296, 1297, 1289, 1287, 1287, 1287, 1288, - 1289, 1289, 1298, 1299, 1300, 1301, 1289, 1289, 1289, 1302, 1303, 1304, - 1305, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, 1287, 1287, - 1287, 1288, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, 1287, - 1287, 1287, 1288, 1289, 1289, 1290, 1287, 1287, 1291, 1289, 1289, 1289, - 1287, 1287, 1287, 1288, 1289, 1289, 1306, 1287, 1287, 1287, 1307, 1289, - 1289, 1308, 1309, 1287, 1287, 1310, 1289, 1289, 1311, 1290, 1287, 1287, - 1312, 1289, 1289, 1313, 1314, 1287, 1287, 1315, 1289, 1289, 1289, 1316, - 1287, 1287, 1287, 1307, 1289, 1289, 1308, 1317, 1318, 1318, 1318, 1318, - 1318, 1318, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, - 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, - 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1319, 1320, 1320, - 1320, 1320, 1320, 1320, 1321, 1322, 1320, 1320, 1320, 1320, 1320, 1323, - 1324, 1319, 1325, 1326, 120, 1327, 1328, 1320, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 1329, 1330, 1330, 1331, 1332, 1333, 120, 120, + 120, 120, 120, 120, 120, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, + 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, + 1329, 1329, 1329, 1329, 1330, 1331, 1332, 120, 120, 120, 120, 120, 1333, + 1333, 1333, 1333, 1334, 1335, 1335, 1335, 1336, 1337, 1338, 1339, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 1334, 1334, 1334, 1334, - 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, - 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1335, 1336, 1337, 120, - 120, 120, 120, 120, 1338, 1338, 1338, 1338, 1339, 1340, 1340, 1340, 1341, - 1342, 1343, 1344, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 1345, 128, 128, 128, 1346, - 1347, 1348, 1349, 1350, 1351, 1346, 1352, 1346, 1348, 1348, 1353, 128, - 1354, 128, 1355, 1356, 1354, 128, 1355, 120, 120, 120, 120, 120, 120, - 1357, 120, 1358, 1359, 1359, 1359, 1359, 1360, 1359, 1359, 1359, 1359, - 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1360, 1361, 1359, 1362, - 1363, 1359, 1363, 1364, 1363, 1359, 1359, 1359, 1365, 1361, 626, 1366, - 628, 628, 628, 1367, 628, 628, 628, 628, 628, 628, 628, 1368, 628, 628, - 628, 1369, 1370, 1371, 628, 1372, 1361, 1361, 1361, 1361, 1361, 1361, - 1373, 1374, 1374, 1374, 1375, 1361, 790, 790, 790, 790, 790, 1376, 790, - 1377, 1378, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 757, - 757, 757, 757, 1379, 1380, 1381, 757, 757, 757, 757, 757, 757, 757, 757, - 1382, 1383, 757, 1384, 1385, 757, 757, 1386, 1387, 1388, 1389, 1384, - 1359, 757, 757, 1390, 1391, 757, 757, 757, 757, 757, 757, 757, 1392, - 1393, 1394, 1395, 757, 1396, 1397, 1394, 1398, 1399, 757, 757, 757, 1400, - 1401, 1402, 757, 757, 757, 757, 757, 757, 757, 757, 1403, 1404, 757, - 1405, 649, 1406, 757, 1407, 1408, 579, 1409, 757, 757, 757, 1359, 1410, - 1411, 1359, 1359, 1412, 1359, 1358, 1359, 1359, 1359, 1359, 1359, 1413, - 1414, 1359, 1359, 1413, 1415, 757, 757, 757, 757, 757, 757, 757, 757, - 1416, 1417, 579, 579, 579, 579, 1418, 1419, 757, 757, 757, 757, 1420, - 757, 1421, 757, 1422, 1358, 1423, 1361, 1359, 1424, 1425, 1361, 579, 579, - 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 1426, 1361, - 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 1427, 1361, 1361, 1361, - 1361, 1361, 579, 1426, 579, 579, 579, 579, 579, 579, 579, 1361, 579, - 1428, 579, 579, 579, 579, 579, 1361, 579, 579, 579, 1429, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 757, 1430, - 1431, 1361, 1432, 1433, 757, 1434, 757, 1435, 1361, 1361, 1361, 1361, - 757, 757, 1436, 1361, 1361, 1361, 1361, 1361, 1437, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1438, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 1439, 810, 810, 810, 810, 810, 808, - 808, 808, 808, 808, 808, 1440, 810, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 809, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 917, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 808, 808, 808, 809, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 1441, 1442, 120, 120, 120, 1443, - 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, - 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, - 932, 932, 932, 120, 120, 916, 916, 916, 916, 916, 916, 916, 916, 916, - 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, - 916, 916, 916, 916, 916, 916, 916, 916, 1444, + 120, 120, 120, 120, 120, 1340, 128, 128, 128, 1341, 1342, 1343, 1344, + 1345, 1346, 1341, 1347, 1341, 1343, 1343, 1348, 128, 1349, 128, 1350, + 1351, 1349, 128, 1350, 120, 120, 120, 120, 120, 120, 1352, 120, 1353, + 1354, 1354, 1354, 1354, 1355, 1354, 1354, 1354, 1354, 1354, 1354, 1354, + 1354, 1354, 1354, 1354, 1354, 1355, 1356, 1354, 1357, 1358, 1354, 1358, + 1359, 1358, 1354, 1354, 1354, 1360, 1356, 619, 1361, 621, 621, 621, 1362, + 621, 621, 621, 621, 621, 621, 621, 1363, 621, 621, 621, 1364, 1365, 1366, + 621, 1367, 1356, 1356, 1356, 1356, 1356, 1356, 1368, 1369, 1369, 1369, + 1370, 1356, 758, 758, 758, 758, 758, 1371, 758, 1372, 1373, 1356, 1374, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 725, 725, 725, 725, 1375, 1376, + 1377, 725, 725, 725, 725, 725, 725, 725, 725, 1378, 1379, 725, 1380, + 1381, 725, 725, 1382, 1383, 1384, 1385, 1380, 1354, 725, 725, 1386, 1387, + 725, 725, 725, 725, 725, 725, 725, 1388, 1389, 1390, 1391, 725, 1392, + 1393, 1390, 1394, 1395, 725, 725, 725, 1396, 1397, 1398, 725, 725, 725, + 725, 725, 725, 725, 725, 1399, 1400, 725, 1401, 642, 1402, 725, 1403, + 1404, 580, 1405, 725, 725, 725, 1354, 1406, 1407, 1354, 1354, 1408, 1354, + 1353, 1354, 1354, 1354, 1354, 1354, 1409, 1410, 1354, 1354, 1409, 1411, + 725, 725, 725, 725, 725, 725, 725, 725, 1412, 1413, 580, 580, 580, 580, + 1414, 1415, 725, 725, 725, 725, 1416, 725, 1417, 725, 1418, 1419, 1420, + 1356, 1354, 1421, 1422, 1423, 580, 580, 580, 580, 580, 580, 580, 580, + 580, 580, 580, 580, 580, 580, 1424, 1356, 580, 580, 580, 580, 580, 580, + 580, 580, 580, 580, 1425, 1356, 1356, 1356, 1356, 1356, 580, 1424, 580, + 580, 580, 580, 580, 580, 580, 1356, 580, 1426, 580, 580, 580, 580, 580, + 1356, 580, 580, 580, 1427, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 580, 1424, 725, 1428, 1429, 725, 1390, 1430, 725, 1431, + 725, 725, 725, 1432, 1356, 1356, 725, 725, 725, 1356, 1356, 1356, 1356, + 1356, 1423, 1356, 1433, 1434, 1435, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, 1356, + 1436, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 1437, + 778, 778, 778, 778, 778, 776, 776, 776, 776, 776, 776, 1438, 778, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 777, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 886, 778, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 1439, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 776, 776, 776, + 777, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 778, 778, 778, 778, 1440, 1441, 120, 120, 120, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 120, + 120, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, + 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, + 885, 885, 885, 885, 1443, }; static const unsigned short index2[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 11, 16, 17, 15, 18, 19, 20, 19, 21, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 19, 23, 24, 25, 24, 10, 15, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 27, 17, - 28, 29, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 16, 31, 32, 25, 1, 1, 1, 1, 1, 1, 33, 1, 1, 34, 35, 36, 13, - 37, 13, 38, 39, 40, 41, 42, 43, 25, 44, 45, 28, 46, 47, 48, 48, 49, 50, - 39, 39, 40, 48, 42, 51, 52, 52, 52, 35, 53, 53, 53, 53, 53, 53, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 53, 53, 53, 53, 53, 55, 54, 53, - 53, 53, 53, 53, 54, 56, 56, 56, 57, 57, 57, 57, 56, 57, 56, 56, 56, 57, - 56, 56, 57, 57, 56, 57, 56, 56, 57, 57, 57, 55, 56, 56, 56, 57, 56, 57, - 56, 57, 53, 56, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, 53, 57, - 53, 56, 53, 56, 53, 57, 53, 57, 53, 57, 53, 56, 53, 57, 53, 57, 53, 57, - 53, 57, 53, 57, 54, 56, 53, 56, 54, 56, 53, 57, 53, 57, 56, 53, 57, 53, - 57, 53, 57, 54, 56, 54, 56, 53, 56, 53, 57, 53, 56, 56, 54, 56, 53, 56, - 53, 57, 53, 57, 54, 56, 53, 57, 53, 57, 53, 53, 57, 53, 57, 53, 57, 57, - 57, 53, 53, 57, 53, 57, 53, 53, 57, 53, 53, 53, 57, 57, 53, 53, 53, 53, - 57, 53, 53, 57, 53, 53, 53, 57, 57, 57, 53, 53, 57, 53, 53, 57, 53, 57, - 53, 57, 53, 53, 57, 53, 57, 57, 53, 57, 53, 53, 57, 53, 53, 53, 57, 53, - 57, 53, 53, 57, 57, 58, 53, 57, 57, 57, 58, 58, 58, 58, 53, 59, 57, 53, - 59, 57, 53, 59, 57, 53, 56, 53, 56, 53, 56, 53, 56, 53, 56, 53, 56, 53, - 56, 53, 56, 57, 53, 57, 57, 53, 59, 57, 53, 57, 53, 53, 53, 57, 53, 57, - 57, 57, 57, 57, 57, 57, 53, 53, 57, 53, 53, 57, 57, 53, 57, 53, 53, 53, - 53, 57, 57, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 58, 57, 57, 57, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, - 61, 62, 62, 62, 62, 62, 62, 62, 63, 63, 64, 63, 61, 65, 66, 65, 65, 65, - 66, 65, 61, 61, 67, 62, 63, 63, 63, 63, 63, 63, 40, 40, 40, 40, 63, 40, - 63, 49, 60, 60, 60, 60, 60, 63, 63, 63, 63, 63, 68, 68, 61, 63, 62, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 70, 71, 71, 71, 71, 70, 72, 71, 71, 71, 71, 71, 73, 73, 71, - 71, 71, 71, 73, 73, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 74, 74, - 74, 74, 74, 71, 71, 71, 71, 69, 69, 69, 69, 69, 69, 69, 69, 75, 69, 71, - 71, 71, 69, 69, 69, 71, 71, 76, 69, 69, 69, 71, 71, 71, 71, 69, 70, 71, - 71, 69, 77, 78, 78, 77, 78, 78, 77, 69, 69, 69, 69, 69, 79, 80, 79, 80, - 61, 81, 79, 80, 82, 82, 83, 80, 80, 80, 84, 79, 82, 82, 82, 82, 81, 63, - 79, 85, 79, 79, 79, 82, 79, 82, 79, 79, 80, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 82, 86, 86, 86, 86, 86, 86, 86, - 79, 79, 80, 80, 80, 80, 80, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, - 87, 87, 87, 87, 87, 87, 80, 87, 87, 87, 87, 87, 87, 87, 80, 80, 80, 80, - 80, 79, 80, 80, 79, 79, 79, 80, 80, 80, 79, 80, 79, 80, 79, 80, 79, 80, - 79, 80, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 88, 89, 80, 80, - 80, 80, 79, 80, 90, 79, 80, 79, 79, 80, 80, 79, 79, 79, 91, 92, 91, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, - 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 94, 93, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 91, 94, 91, 94, 91, 94, 91, 94, 91, 94, - 95, 96, 96, 97, 97, 96, 98, 98, 91, 94, 91, 94, 91, 94, 91, 91, 94, 91, - 94, 91, 94, 91, 94, 91, 94, 91, 94, 91, 94, 94, 82, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 82, - 82, 100, 101, 101, 101, 101, 101, 101, 82, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 82, 103, 104, 82, 82, 105, - 105, 106, 82, 107, 108, 108, 108, 108, 107, 108, 108, 108, 109, 107, 108, - 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 108, 108, 107, - 108, 108, 109, 110, 108, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 120, 121, 122, 123, 124, 125, 126, 127, 128, 126, 108, 107, 129, - 119, 82, 82, 82, 82, 82, 82, 82, 82, 130, 130, 130, 130, 130, 130, 130, - 130, 130, 130, 130, 82, 82, 82, 82, 82, 130, 130, 130, 126, 126, 82, 82, - 82, 131, 131, 131, 131, 131, 132, 133, 133, 134, 135, 135, 136, 137, 138, - 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 142, 143, 144, - 145, 82, 146, 144, 147, 147, 147, 147, 147, 147, 147, 147, 148, 147, 147, - 147, 147, 147, 147, 147, 147, 147, 147, 149, 150, 151, 152, 153, 154, - 155, 156, 97, 97, 157, 158, 140, 140, 140, 140, 140, 158, 140, 140, 158, - 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 135, 160, 160, 161, - 147, 147, 162, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, - 146, 147, 140, 140, 140, 140, 140, 140, 140, 132, 139, 140, 140, 140, - 140, 158, 140, 163, 163, 140, 140, 139, 158, 140, 140, 158, 147, 147, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 147, 147, 147, 165, - 165, 147, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, - 166, 166, 82, 167, 168, 169, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 170, 171, 170, 170, 171, 170, 170, 171, 171, - 171, 170, 171, 171, 170, 171, 170, 170, 170, 171, 170, 171, 170, 171, - 170, 171, 170, 170, 82, 82, 168, 168, 168, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 173, 172, 82, 82, 82, 82, 82, 82, 174, 174, 174, 174, - 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 176, - 176, 176, 177, 176, 178, 178, 179, 180, 181, 182, 178, 82, 82, 82, 82, - 82, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, - 184, 184, 184, 184, 185, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 185, 184, 184, 184, 185, 184, 184, 184, 184, 184, 82, 82, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 82, 187, 187, - 187, 187, 187, 187, 187, 187, 187, 188, 188, 188, 82, 82, 189, 82, 147, - 147, 147, 147, 147, 82, 147, 147, 147, 147, 147, 147, 147, 147, 82, 82, - 82, 82, 82, 82, 140, 140, 140, 140, 140, 140, 132, 158, 140, 140, 158, - 140, 140, 158, 140, 140, 140, 158, 158, 158, 190, 191, 192, 140, 140, - 140, 158, 140, 140, 158, 158, 140, 140, 140, 140, 140, 193, 193, 193, - 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 193, 194, 196, 195, 194, 194, 194, 193, 193, 193, 193, 193, 193, - 193, 193, 194, 194, 194, 194, 197, 194, 194, 195, 97, 157, 198, 198, 193, - 193, 193, 195, 195, 193, 193, 199, 199, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 201, 202, 195, 195, 195, 195, 195, 195, 203, 204, - 205, 205, 82, 203, 203, 203, 203, 203, 203, 203, 203, 82, 82, 203, 203, - 82, 82, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 82, 203, 203, 203, 203, 203, 203, 203, 82, 203, 82, 82, 82, 203, - 203, 203, 203, 82, 82, 206, 203, 205, 205, 205, 204, 204, 204, 204, 82, - 82, 205, 205, 82, 82, 205, 205, 207, 203, 82, 82, 82, 82, 82, 82, 82, 82, - 205, 82, 82, 82, 82, 203, 203, 82, 203, 203, 203, 204, 204, 82, 82, 208, - 208, 208, 208, 208, 208, 208, 208, 208, 208, 203, 203, 209, 209, 210, - 210, 210, 210, 210, 211, 212, 213, 82, 82, 82, 82, 82, 214, 214, 215, 82, - 216, 216, 216, 216, 216, 216, 82, 82, 82, 82, 216, 216, 82, 82, 216, 216, - 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 82, 216, 216, - 216, 216, 216, 216, 216, 82, 216, 216, 82, 216, 216, 82, 216, 216, 82, - 82, 217, 82, 215, 215, 215, 214, 214, 82, 82, 82, 82, 214, 214, 82, 82, - 214, 214, 218, 82, 82, 82, 214, 82, 82, 82, 82, 82, 82, 82, 216, 216, - 216, 216, 82, 216, 82, 82, 82, 82, 82, 82, 82, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 214, 214, 216, 216, 216, 214, 82, 82, 82, 220, - 220, 221, 82, 222, 222, 222, 222, 222, 222, 222, 222, 222, 82, 222, 222, - 222, 82, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, - 222, 82, 222, 222, 222, 222, 222, 222, 222, 82, 222, 222, 82, 222, 222, - 222, 222, 222, 82, 82, 223, 222, 221, 221, 221, 220, 220, 220, 220, 220, - 82, 220, 220, 221, 82, 221, 221, 224, 82, 82, 222, 82, 82, 82, 82, 82, - 82, 82, 222, 222, 220, 220, 82, 82, 225, 225, 225, 225, 225, 225, 225, - 225, 225, 225, 226, 227, 82, 82, 82, 82, 82, 82, 82, 222, 82, 82, 82, 82, - 82, 82, 82, 228, 229, 229, 82, 230, 230, 230, 230, 230, 230, 230, 230, - 82, 82, 230, 230, 82, 82, 230, 230, 230, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 82, 230, 230, 230, 230, 230, 230, 230, 82, 230, - 230, 82, 230, 230, 230, 230, 230, 82, 82, 231, 230, 229, 228, 229, 228, - 228, 228, 228, 82, 82, 229, 229, 82, 82, 229, 229, 232, 82, 82, 82, 82, - 82, 82, 82, 82, 228, 229, 82, 82, 82, 82, 230, 230, 82, 230, 230, 230, - 228, 228, 82, 82, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 234, - 230, 235, 235, 235, 235, 235, 235, 82, 82, 236, 237, 82, 237, 237, 237, - 237, 237, 237, 82, 82, 82, 237, 237, 237, 82, 237, 237, 237, 237, 82, 82, - 82, 237, 237, 82, 237, 82, 237, 237, 82, 82, 82, 237, 237, 82, 82, 82, - 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 82, 82, 82, 82, 238, - 238, 236, 238, 238, 82, 82, 82, 238, 238, 238, 82, 238, 238, 238, 239, - 82, 82, 237, 82, 82, 82, 82, 82, 82, 238, 82, 82, 82, 82, 82, 82, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, 241, 242, 242, - 242, 242, 242, 242, 243, 242, 82, 82, 82, 82, 82, 244, 245, 245, 245, 82, - 246, 246, 246, 246, 246, 246, 246, 246, 82, 246, 246, 246, 82, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 82, - 82, 82, 246, 244, 244, 244, 245, 245, 245, 245, 82, 244, 244, 244, 82, - 244, 244, 244, 247, 82, 82, 82, 82, 82, 82, 82, 248, 249, 82, 246, 246, - 246, 82, 82, 82, 82, 82, 246, 246, 244, 244, 82, 82, 250, 250, 250, 250, - 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 252, - 253, 254, 255, 255, 82, 253, 253, 253, 253, 253, 253, 253, 253, 82, 253, - 253, 253, 82, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, - 253, 253, 253, 253, 253, 253, 82, 253, 253, 253, 253, 253, 82, 82, 256, - 253, 255, 257, 255, 255, 255, 255, 255, 82, 257, 255, 255, 82, 255, 255, - 254, 258, 82, 82, 82, 82, 82, 82, 82, 255, 255, 82, 82, 82, 82, 82, 82, - 82, 253, 82, 253, 253, 254, 254, 82, 82, 259, 259, 259, 259, 259, 259, - 259, 259, 259, 259, 82, 253, 253, 82, 82, 82, 82, 82, 82, 260, 261, 261, - 82, 262, 262, 262, 262, 262, 262, 262, 262, 82, 262, 262, 262, 82, 262, - 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, - 262, 262, 82, 82, 262, 261, 261, 261, 260, 260, 260, 260, 82, 261, 261, - 261, 82, 261, 261, 261, 263, 262, 264, 82, 82, 82, 82, 262, 262, 262, - 261, 265, 265, 265, 265, 265, 265, 265, 262, 262, 262, 260, 260, 82, 82, - 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 265, 265, 265, 265, - 265, 265, 265, 265, 265, 267, 262, 262, 262, 262, 262, 262, 82, 82, 268, - 268, 82, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, - 269, 269, 269, 269, 269, 82, 82, 82, 269, 269, 269, 269, 269, 269, 269, - 269, 82, 269, 269, 269, 269, 269, 269, 269, 269, 269, 82, 269, 82, 82, - 82, 82, 270, 82, 82, 82, 82, 268, 268, 268, 271, 271, 271, 82, 271, 82, - 268, 268, 268, 268, 268, 268, 268, 268, 82, 82, 82, 82, 82, 82, 272, 272, - 272, 272, 272, 272, 272, 272, 272, 272, 82, 82, 268, 268, 273, 82, 82, - 82, 82, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 275, 274, 274, 275, 275, 275, 275, 276, 276, 277, 82, 82, - 82, 82, 278, 274, 274, 274, 274, 274, 274, 279, 275, 280, 280, 280, 280, - 275, 275, 275, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 283, 283, 82, 82, 82, 82, 82, 284, 284, 82, 284, 82, 82, 284, 284, 82, - 284, 82, 82, 284, 82, 82, 82, 82, 82, 82, 284, 284, 284, 284, 82, 284, - 284, 284, 284, 284, 284, 284, 82, 284, 284, 284, 82, 284, 82, 284, 82, - 82, 284, 284, 82, 284, 284, 284, 284, 285, 284, 284, 285, 285, 285, 285, - 286, 286, 82, 285, 285, 284, 82, 82, 284, 284, 284, 284, 284, 82, 287, - 82, 288, 288, 288, 288, 285, 285, 82, 82, 289, 289, 289, 289, 289, 289, - 289, 289, 289, 289, 82, 82, 284, 284, 284, 284, 290, 291, 291, 291, 292, - 293, 292, 292, 294, 292, 292, 295, 294, 296, 296, 296, 296, 296, 294, - 297, 296, 297, 297, 297, 298, 298, 297, 297, 297, 297, 297, 297, 299, - 299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 300, 300, 300, 300, - 300, 300, 300, 300, 300, 301, 298, 297, 298, 297, 302, 303, 304, 303, - 304, 305, 305, 290, 290, 290, 290, 290, 290, 290, 290, 82, 290, 290, 290, - 290, 290, 290, 290, 290, 290, 290, 290, 290, 82, 82, 82, 82, 306, 307, - 308, 309, 308, 308, 308, 308, 308, 307, 307, 307, 307, 308, 310, 307, - 308, 311, 311, 312, 295, 311, 311, 290, 290, 290, 290, 290, 308, 308, - 308, 308, 308, 308, 308, 308, 308, 308, 308, 82, 308, 308, 308, 308, 308, - 308, 308, 308, 308, 308, 308, 308, 82, 301, 301, 297, 297, 297, 297, 297, - 297, 298, 297, 297, 297, 297, 297, 297, 82, 297, 297, 292, 292, 295, 292, - 293, 313, 313, 313, 313, 294, 294, 82, 82, 82, 82, 82, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 315, 315, 316, 316, 316, 316, - 315, 316, 316, 316, 316, 316, 317, 315, 318, 318, 315, 315, 316, 316, - 314, 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, 320, 320, 321, - 321, 321, 321, 314, 314, 314, 314, 314, 314, 315, 315, 316, 316, 314, - 314, 314, 314, 316, 316, 316, 314, 315, 315, 315, 314, 314, 315, 315, - 315, 315, 315, 315, 315, 314, 314, 314, 316, 316, 316, 316, 314, 314, - 314, 314, 314, 316, 315, 315, 316, 316, 315, 315, 315, 315, 315, 315, - 322, 314, 315, 319, 319, 315, 315, 315, 316, 323, 323, 324, 324, 324, - 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, 82, 324, 82, 82, - 82, 82, 82, 324, 82, 82, 325, 325, 325, 325, 325, 325, 325, 325, 325, - 325, 325, 326, 327, 325, 325, 325, 328, 328, 328, 328, 328, 328, 328, - 328, 329, 329, 329, 329, 329, 329, 329, 329, 330, 330, 330, 330, 330, - 330, 330, 330, 331, 331, 331, 331, 331, 331, 331, 331, 331, 82, 331, 331, - 331, 331, 82, 82, 331, 331, 331, 331, 331, 331, 331, 82, 331, 331, 331, - 82, 82, 332, 332, 332, 333, 334, 333, 333, 333, 333, 333, 333, 333, 335, - 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 82, 82, 82, 336, 336, 336, 336, 336, 336, 336, - 336, 336, 336, 82, 82, 82, 82, 82, 82, 337, 337, 337, 337, 337, 337, 337, - 337, 337, 337, 337, 337, 337, 337, 82, 82, 338, 338, 338, 338, 338, 338, - 82, 82, 339, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, - 340, 340, 340, 340, 340, 340, 340, 340, 341, 341, 340, 342, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 344, 345, 82, 82, 82, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 199, 199, 199, 347, 347, 347, 346, 346, 346, 346, 346, - 346, 346, 346, 82, 82, 82, 82, 82, 82, 82, 348, 348, 348, 348, 348, 348, - 348, 348, 348, 348, 348, 348, 348, 82, 348, 348, 348, 348, 349, 349, 350, - 82, 82, 82, 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, 352, 352, - 353, 199, 199, 82, 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, 355, - 355, 82, 82, 82, 82, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, - 356, 356, 356, 82, 356, 356, 356, 82, 357, 357, 82, 82, 82, 82, 358, 358, - 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 359, 359, 360, 359, - 359, 359, 359, 359, 359, 359, 360, 360, 360, 360, 360, 360, 360, 360, - 359, 360, 360, 359, 359, 359, 359, 359, 359, 359, 359, 359, 361, 359, - 362, 362, 363, 364, 362, 365, 362, 366, 358, 367, 82, 82, 368, 368, 368, - 368, 368, 368, 368, 368, 368, 368, 82, 82, 82, 82, 82, 82, 369, 369, 369, - 369, 369, 369, 369, 369, 369, 369, 82, 82, 82, 82, 82, 82, 370, 370, 371, - 371, 372, 373, 374, 370, 375, 375, 370, 376, 376, 376, 377, 82, 378, 378, - 378, 378, 378, 378, 378, 378, 378, 378, 82, 82, 82, 82, 82, 82, 379, 379, - 379, 379, 379, 379, 379, 379, 379, 379, 379, 380, 379, 379, 379, 379, - 379, 379, 379, 379, 379, 376, 376, 379, 379, 381, 379, 82, 82, 82, 82, - 82, 340, 340, 340, 340, 340, 340, 82, 82, 382, 382, 382, 382, 382, 382, - 382, 382, 382, 382, 382, 382, 382, 382, 382, 82, 383, 383, 383, 384, 384, - 384, 384, 383, 383, 384, 384, 384, 82, 82, 82, 82, 384, 384, 383, 384, - 384, 384, 384, 384, 384, 385, 386, 387, 82, 82, 82, 82, 388, 82, 82, 82, - 389, 389, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, - 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 82, 82, 391, - 391, 391, 391, 391, 82, 82, 82, 392, 392, 392, 392, 392, 392, 392, 392, - 392, 392, 392, 392, 82, 82, 82, 82, 392, 392, 82, 82, 82, 82, 82, 82, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 394, 82, 82, 82, 395, - 395, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, - 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, 398, 399, 400, 400, - 401, 82, 82, 402, 402, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, - 403, 403, 403, 404, 405, 404, 405, 405, 405, 405, 405, 405, 405, 82, 406, - 404, 405, 404, 404, 405, 405, 405, 405, 405, 405, 405, 405, 404, 404, - 404, 404, 404, 404, 405, 405, 407, 407, 407, 407, 407, 407, 407, 407, 82, - 82, 408, 409, 409, 409, 409, 409, 409, 409, 409, 409, 409, 82, 82, 82, - 82, 82, 82, 410, 410, 410, 410, 410, 410, 410, 411, 410, 410, 410, 410, - 410, 410, 82, 82, 97, 97, 97, 97, 97, 157, 157, 157, 157, 157, 157, 97, - 97, 157, 412, 82, 413, 413, 413, 413, 414, 415, 415, 415, 415, 415, 415, - 415, 415, 415, 415, 415, 415, 415, 415, 415, 416, 414, 413, 413, 413, - 413, 413, 414, 413, 414, 414, 414, 414, 414, 413, 414, 417, 415, 415, - 415, 415, 415, 415, 415, 82, 82, 82, 82, 418, 418, 418, 418, 418, 418, - 418, 418, 418, 418, 419, 419, 420, 419, 419, 419, 419, 421, 421, 421, - 421, 421, 421, 421, 421, 421, 421, 422, 423, 422, 422, 422, 422, 422, - 422, 422, 421, 421, 421, 421, 421, 421, 421, 421, 421, 82, 82, 82, 424, - 424, 425, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, - 426, 426, 425, 424, 424, 424, 424, 425, 425, 424, 424, 427, 428, 424, - 424, 426, 426, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 426, - 426, 426, 426, 426, 426, 430, 430, 430, 430, 430, 430, 430, 430, 430, - 430, 430, 430, 430, 430, 431, 432, 433, 433, 432, 432, 432, 433, 432, - 433, 433, 433, 434, 434, 82, 82, 82, 82, 82, 82, 82, 82, 435, 435, 435, - 435, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 437, - 437, 437, 437, 437, 437, 437, 437, 438, 438, 438, 438, 438, 438, 438, - 438, 437, 437, 438, 439, 82, 82, 82, 440, 440, 440, 440, 440, 441, 441, - 441, 441, 441, 441, 441, 441, 441, 441, 82, 82, 82, 436, 436, 436, 442, - 442, 442, 442, 442, 442, 442, 442, 442, 442, 443, 443, 443, 443, 443, - 443, 443, 443, 443, 443, 443, 443, 443, 443, 444, 444, 444, 444, 444, - 444, 445, 445, 94, 82, 82, 82, 82, 82, 82, 82, 446, 446, 446, 446, 446, - 446, 446, 446, 97, 97, 97, 326, 447, 157, 157, 157, 157, 157, 97, 97, - 157, 157, 157, 157, 97, 448, 447, 447, 447, 447, 447, 447, 447, 449, 449, - 449, 449, 157, 449, 449, 449, 449, 448, 448, 97, 449, 449, 82, 97, 97, - 82, 82, 82, 82, 82, 82, 57, 57, 57, 57, 57, 57, 80, 80, 80, 80, 80, 94, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 83, 83, 83, 83, 83, 60, 60, 60, 60, - 83, 83, 83, 83, 83, 57, 57, 57, 57, 57, 450, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 83, 97, 97, - 157, 97, 97, 97, 97, 97, 97, 97, 157, 97, 97, 451, 452, 157, 453, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 82, 82, 82, 82, 82, 97, 454, 157, 97, 157, 53, 57, 53, 57, 53, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 53, 57, 80, 80, 80, 80, 80, 80, 80, 80, - 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 82, 82, 79, 79, - 79, 79, 79, 79, 82, 82, 82, 79, 82, 79, 82, 79, 82, 79, 455, 455, 455, - 455, 455, 455, 455, 455, 80, 80, 80, 80, 80, 82, 80, 80, 79, 79, 79, 79, - 455, 81, 80, 81, 81, 81, 80, 80, 80, 82, 80, 80, 79, 79, 79, 79, 455, 81, - 81, 81, 80, 80, 80, 80, 82, 82, 80, 80, 79, 79, 79, 79, 82, 81, 81, 81, - 79, 79, 79, 79, 79, 81, 81, 81, 82, 82, 80, 80, 80, 82, 80, 80, 79, 79, - 79, 79, 455, 456, 81, 82, 457, 457, 457, 457, 457, 457, 457, 458, 457, - 457, 457, 459, 460, 461, 462, 463, 464, 465, 466, 464, 467, 468, 39, 85, - 469, 470, 471, 472, 469, 470, 471, 472, 39, 39, 473, 85, 474, 474, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 34, 483, 484, 483, 483, 484, 485, - 486, 486, 85, 43, 51, 39, 487, 487, 473, 488, 488, 85, 85, 85, 489, 490, - 491, 487, 487, 487, 85, 85, 85, 85, 85, 85, 85, 85, 492, 85, 488, 85, - 373, 85, 373, 373, 373, 373, 85, 373, 373, 457, 493, 494, 494, 494, 494, - 82, 495, 496, 497, 498, 499, 499, 499, 499, 499, 499, 500, 60, 82, 82, - 48, 500, 500, 500, 500, 500, 501, 501, 492, 490, 491, 502, 500, 48, 48, - 48, 48, 500, 500, 500, 500, 500, 501, 501, 492, 490, 491, 82, 60, 60, 60, - 60, 60, 82, 82, 82, 278, 278, 278, 278, 278, 278, 278, 503, 278, 504, - 278, 278, 37, 278, 278, 278, 278, 278, 278, 278, 278, 278, 503, 278, 278, - 278, 278, 503, 278, 278, 503, 505, 505, 505, 505, 505, 505, 505, 505, - 505, 97, 97, 447, 447, 97, 97, 97, 97, 447, 447, 447, 97, 97, 412, 412, - 412, 412, 97, 412, 412, 412, 447, 447, 97, 157, 97, 447, 447, 157, 157, - 157, 157, 97, 82, 82, 82, 82, 82, 82, 82, 41, 41, 506, 507, 41, 508, 41, - 506, 41, 507, 50, 506, 506, 506, 50, 50, 506, 506, 506, 509, 41, 506, - 510, 41, 492, 506, 506, 506, 506, 506, 41, 41, 41, 508, 508, 41, 506, 41, - 86, 41, 506, 41, 53, 511, 506, 506, 512, 50, 506, 506, 53, 506, 50, 449, - 449, 449, 449, 50, 41, 41, 50, 50, 506, 506, 513, 492, 492, 492, 492, - 506, 50, 50, 50, 50, 41, 492, 41, 41, 57, 313, 514, 514, 514, 515, 52, - 516, 514, 514, 514, 514, 514, 52, 515, 515, 52, 514, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 518, 518, 518, 518, 517, 517, - 518, 518, 518, 518, 518, 518, 518, 518, 518, 53, 57, 518, 518, 518, 518, - 52, 41, 41, 82, 82, 82, 82, 55, 55, 55, 55, 55, 508, 508, 508, 508, 508, - 492, 492, 41, 41, 41, 41, 492, 41, 41, 492, 41, 41, 492, 41, 41, 41, 41, - 41, 41, 41, 492, 41, 41, 41, 41, 41, 41, 41, 41, 41, 45, 45, 41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 492, 492, 41, 41, 55, 41, 55, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, 45, 41, 41, 41, 41, 492, 492, 492, 492, - 492, 492, 492, 492, 492, 492, 492, 492, 55, 513, 519, 519, 513, 492, 492, - 55, 519, 513, 513, 519, 513, 513, 492, 55, 492, 519, 520, 521, 492, 519, - 513, 492, 492, 492, 519, 513, 513, 519, 55, 519, 519, 513, 513, 55, 513, - 55, 513, 55, 55, 55, 55, 519, 519, 513, 519, 513, 513, 513, 513, 513, 55, - 55, 55, 55, 492, 513, 492, 513, 519, 519, 513, 513, 513, 513, 513, 513, - 513, 513, 513, 513, 519, 513, 513, 513, 519, 492, 492, 492, 492, 492, - 519, 513, 513, 513, 492, 492, 492, 492, 492, 492, 492, 492, 492, 513, - 519, 55, 513, 492, 519, 519, 519, 519, 513, 513, 519, 519, 492, 492, 519, - 519, 513, 513, 519, 519, 513, 513, 519, 519, 513, 513, 513, 513, 513, - 492, 492, 513, 513, 513, 513, 492, 492, 55, 492, 492, 513, 55, 492, 492, - 492, 492, 492, 492, 492, 492, 513, 513, 492, 55, 513, 513, 513, 492, 492, - 492, 492, 492, 513, 519, 492, 513, 513, 513, 513, 513, 492, 492, 513, - 513, 492, 492, 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 492, - 522, 490, 491, 490, 491, 41, 41, 41, 41, 41, 41, 508, 41, 41, 41, 41, 41, - 41, 41, 523, 523, 41, 41, 41, 41, 513, 513, 41, 41, 41, 41, 41, 41, 41, - 524, 525, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 313, 313, 313, 313, - 313, 313, 313, 313, 313, 313, 313, 313, 313, 41, 492, 41, 41, 41, 41, 41, - 41, 41, 41, 313, 41, 41, 41, 41, 41, 492, 492, 492, 492, 492, 492, 492, - 492, 492, 41, 41, 41, 41, 492, 492, 41, 41, 41, 41, 41, 41, 41, 526, 526, - 526, 526, 41, 41, 41, 523, 527, 527, 523, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 41, 82, 41, 41, 41, 82, 82, 82, 82, 82, 52, 52, 52, 52, 52, 52, - 52, 52, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 528, 528, 528, - 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 516, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 515, 508, 508, 508, 508, 508, 508, - 508, 508, 508, 508, 508, 508, 41, 41, 41, 41, 508, 508, 508, 508, 529, - 41, 41, 41, 41, 41, 508, 508, 508, 508, 41, 41, 508, 508, 41, 508, 508, - 508, 508, 508, 508, 508, 41, 41, 41, 41, 41, 41, 41, 41, 508, 508, 41, - 41, 508, 55, 41, 41, 41, 41, 508, 508, 41, 41, 508, 55, 41, 41, 41, 41, - 508, 508, 508, 41, 41, 508, 41, 41, 508, 508, 41, 41, 41, 41, 41, 41, 41, - 508, 492, 492, 492, 492, 492, 530, 530, 492, 527, 527, 527, 527, 41, 508, - 508, 41, 41, 508, 41, 41, 41, 41, 508, 508, 41, 41, 41, 41, 523, 523, - 529, 529, 527, 41, 527, 527, 531, 532, 531, 527, 41, 527, 527, 527, 41, - 41, 41, 41, 508, 41, 508, 41, 41, 41, 41, 41, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 41, 41, 41, 41, 508, 508, 41, 508, - 508, 508, 41, 508, 531, 508, 508, 41, 508, 508, 41, 55, 41, 41, 41, 41, - 41, 41, 41, 523, 41, 41, 41, 526, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 508, 508, 41, 526, 41, 41, 41, 41, 41, 41, 41, 41, 526, 526, 313, 41, 41, - 41, 41, 41, 41, 41, 41, 523, 523, 531, 527, 527, 527, 527, 523, 523, 531, - 531, 531, 508, 508, 508, 508, 531, 526, 531, 531, 531, 508, 531, 523, - 508, 508, 508, 531, 531, 508, 508, 531, 508, 508, 531, 531, 531, 41, 508, - 41, 41, 41, 41, 508, 508, 523, 508, 508, 508, 508, 508, 508, 531, 523, - 523, 531, 523, 508, 531, 531, 533, 523, 508, 508, 523, 531, 531, 527, - 527, 527, 527, 527, 526, 41, 41, 527, 527, 534, 534, 532, 532, 41, 41, - 526, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 45, 41, 41, 41, 41, - 41, 41, 526, 41, 526, 41, 41, 41, 41, 526, 526, 526, 41, 535, 41, 41, 41, - 536, 536, 536, 536, 536, 536, 41, 537, 537, 527, 41, 41, 41, 490, 491, - 490, 491, 490, 491, 490, 491, 490, 491, 490, 491, 490, 491, 52, 52, 516, - 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, 41, 526, 526, 526, - 41, 41, 41, 41, 41, 41, 41, 526, 513, 492, 492, 513, 513, 490, 491, 492, - 513, 513, 492, 513, 513, 513, 492, 492, 492, 492, 492, 513, 513, 513, - 513, 492, 492, 492, 492, 492, 513, 513, 513, 492, 492, 492, 513, 513, - 513, 513, 16, 32, 16, 32, 16, 32, 16, 32, 490, 491, 538, 538, 538, 538, - 538, 538, 538, 538, 492, 492, 492, 490, 491, 16, 32, 490, 491, 490, 491, - 490, 491, 490, 491, 490, 491, 492, 492, 513, 513, 513, 513, 513, 513, - 492, 492, 492, 492, 492, 492, 492, 513, 513, 513, 513, 513, 513, 492, - 492, 492, 513, 492, 492, 492, 492, 513, 513, 513, 513, 513, 492, 513, - 513, 492, 492, 490, 491, 490, 491, 513, 492, 492, 492, 492, 513, 492, - 513, 513, 513, 492, 492, 513, 513, 492, 492, 492, 492, 492, 492, 492, - 492, 492, 492, 513, 513, 513, 513, 513, 513, 492, 492, 490, 491, 492, - 492, 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, - 492, 513, 513, 513, 513, 492, 492, 513, 492, 513, 492, 492, 513, 492, - 513, 513, 513, 513, 492, 492, 492, 492, 492, 513, 513, 492, 492, 492, - 492, 513, 513, 513, 513, 492, 513, 513, 492, 492, 513, 513, 492, 492, - 492, 492, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, 492, - 492, 513, 513, 513, 513, 513, 513, 513, 513, 492, 513, 513, 513, 513, - 513, 513, 513, 513, 492, 492, 492, 492, 492, 513, 492, 513, 492, 492, - 492, 513, 513, 513, 513, 513, 492, 492, 492, 492, 513, 492, 492, 492, - 513, 513, 513, 513, 513, 492, 513, 492, 492, 41, 41, 41, 526, 526, 41, - 41, 41, 492, 492, 492, 492, 492, 41, 41, 492, 492, 492, 492, 492, 492, - 41, 41, 41, 526, 41, 41, 41, 41, 535, 508, 508, 41, 41, 41, 41, 82, 82, - 41, 41, 41, 41, 41, 41, 41, 41, 82, 82, 41, 41, 82, 82, 82, 41, 41, 41, - 41, 82, 41, 41, 41, 41, 41, 41, 41, 41, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 41, 41, 41, 41, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, - 539, 539, 539, 539, 539, 82, 540, 540, 540, 540, 540, 540, 540, 540, 540, - 540, 540, 540, 540, 540, 540, 82, 53, 57, 53, 53, 53, 57, 57, 53, 57, 53, - 57, 53, 57, 53, 53, 53, 53, 57, 53, 57, 57, 53, 57, 57, 57, 57, 57, 57, - 60, 60, 53, 53, 88, 89, 88, 89, 89, 541, 541, 541, 541, 541, 541, 88, 89, - 88, 89, 542, 542, 542, 88, 89, 82, 82, 82, 82, 82, 543, 544, 544, 544, - 545, 543, 544, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, - 546, 546, 546, 82, 546, 82, 82, 82, 82, 82, 546, 82, 82, 547, 547, 547, - 547, 547, 547, 547, 547, 82, 82, 82, 82, 82, 82, 82, 548, 549, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 550, 96, 96, 96, 96, 96, - 96, 96, 96, 551, 551, 43, 51, 43, 51, 551, 551, 551, 43, 51, 551, 43, 51, - 373, 373, 373, 373, 373, 373, 373, 373, 85, 466, 552, 373, 553, 85, 43, - 51, 85, 85, 43, 51, 490, 491, 490, 491, 490, 491, 490, 491, 373, 373, - 373, 373, 371, 61, 373, 373, 85, 373, 373, 85, 85, 85, 85, 85, 554, 554, - 373, 373, 373, 85, 466, 373, 471, 373, 373, 82, 82, 82, 555, 555, 555, - 555, 555, 555, 555, 555, 555, 555, 82, 555, 555, 555, 555, 555, 555, 555, - 555, 555, 82, 82, 82, 82, 555, 555, 555, 555, 555, 555, 82, 82, 523, 523, - 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 82, 82, 82, 82, 556, - 557, 557, 558, 523, 559, 560, 561, 524, 525, 524, 525, 524, 525, 524, - 525, 524, 525, 523, 523, 524, 525, 524, 525, 524, 525, 524, 525, 562, - 563, 564, 564, 523, 561, 561, 561, 561, 561, 561, 561, 561, 561, 565, - 566, 567, 568, 569, 569, 570, 571, 571, 571, 571, 572, 523, 523, 561, - 561, 561, 559, 573, 558, 523, 527, 82, 574, 575, 574, 575, 574, 575, 574, - 575, 574, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, - 575, 575, 575, 575, 575, 574, 575, 575, 575, 575, 575, 575, 575, 574, - 575, 574, 575, 574, 575, 575, 575, 575, 575, 575, 574, 575, 575, 575, - 575, 575, 575, 574, 574, 82, 82, 576, 576, 577, 577, 578, 578, 575, 562, - 579, 580, 579, 580, 579, 580, 579, 580, 579, 580, 580, 580, 580, 580, - 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 579, 580, - 580, 580, 580, 580, 580, 580, 579, 580, 579, 580, 579, 580, 580, 580, - 580, 580, 580, 579, 580, 580, 580, 580, 580, 580, 579, 579, 580, 580, - 580, 580, 581, 582, 583, 583, 580, 82, 82, 82, 82, 82, 584, 584, 584, - 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 584, 82, - 82, 82, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, - 585, 585, 585, 585, 585, 585, 585, 585, 585, 82, 586, 586, 587, 587, 587, - 587, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 584, 584, 584, 82, - 82, 82, 82, 82, 579, 579, 579, 579, 579, 579, 579, 579, 588, 588, 588, - 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 589, 589, 82, 587, 587, - 587, 587, 587, 587, 587, 587, 587, 587, 586, 586, 586, 586, 586, 586, - 590, 590, 590, 590, 590, 590, 590, 590, 523, 591, 591, 591, 591, 591, - 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 588, 588, 588, 588, - 589, 589, 589, 586, 586, 591, 591, 591, 591, 591, 591, 591, 586, 586, - 586, 586, 523, 523, 523, 523, 592, 592, 592, 592, 592, 592, 592, 592, - 592, 592, 592, 592, 592, 592, 592, 82, 586, 586, 586, 586, 586, 586, 586, - 523, 523, 523, 523, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 586, 523, 523, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, - 593, 593, 593, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595, - 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 596, 595, - 595, 595, 595, 595, 595, 595, 82, 82, 82, 597, 597, 597, 597, 597, 597, - 597, 597, 597, 597, 597, 597, 597, 597, 597, 82, 598, 598, 598, 598, 598, - 598, 598, 598, 599, 599, 599, 599, 599, 599, 600, 600, 601, 601, 601, - 601, 601, 601, 601, 601, 601, 601, 601, 601, 602, 603, 604, 603, 605, - 605, 605, 605, 605, 605, 605, 605, 605, 605, 601, 601, 82, 82, 82, 82, - 91, 94, 91, 94, 91, 94, 606, 96, 98, 98, 98, 607, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 607, 608, 91, 94, 91, 94, 450, 450, 96, 96, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 610, 610, - 610, 610, 610, 610, 610, 610, 610, 610, 611, 611, 612, 613, 613, 613, - 613, 613, 63, 63, 63, 63, 63, 63, 63, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 63, 63, 53, 57, 53, 57, 53, 57, 57, 57, 53, 57, 53, 57, 53, 57, 60, 57, - 57, 57, 57, 57, 57, 57, 57, 53, 57, 53, 57, 53, 53, 57, 61, 614, 614, 53, - 57, 53, 57, 58, 53, 57, 53, 57, 57, 57, 53, 57, 53, 57, 53, 53, 53, 53, - 53, 82, 53, 53, 53, 53, 53, 57, 53, 57, 82, 82, 82, 82, 82, 82, 82, 58, - 60, 60, 57, 58, 58, 58, 58, 58, 615, 615, 616, 615, 615, 615, 617, 615, - 615, 615, 615, 616, 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 618, 618, 616, 616, 618, 619, 619, 619, 619, 82, - 82, 82, 82, 620, 620, 620, 620, 620, 620, 313, 313, 503, 512, 82, 82, 82, - 82, 82, 82, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, - 622, 622, 623, 623, 624, 624, 625, 625, 625, 625, 625, 625, 625, 625, - 625, 625, 625, 625, 625, 625, 625, 625, 625, 625, 624, 624, 624, 624, - 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 626, 627, 82, - 82, 82, 82, 82, 82, 82, 82, 628, 628, 629, 629, 629, 629, 629, 629, 629, - 629, 629, 629, 82, 82, 82, 82, 82, 82, 198, 198, 198, 198, 198, 198, 198, - 198, 198, 198, 195, 195, 195, 195, 195, 195, 201, 201, 201, 195, 630, - 195, 82, 82, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 632, 632, - 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, - 632, 632, 632, 632, 633, 633, 633, 633, 633, 634, 634, 634, 199, 635, - 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, - 636, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 638, 639, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 640, 328, 328, 328, 328, 328, 82, - 82, 82, 641, 641, 641, 642, 643, 643, 643, 643, 643, 643, 643, 643, 643, - 643, 643, 643, 643, 643, 643, 644, 642, 642, 641, 641, 641, 641, 642, - 642, 641, 642, 642, 642, 645, 646, 646, 646, 646, 646, 646, 647, 647, - 647, 646, 646, 646, 646, 82, 62, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 82, 82, 82, 82, 646, 646, 314, 314, 314, 314, 314, 316, 649, - 314, 319, 319, 314, 314, 314, 314, 314, 82, 650, 650, 650, 650, 650, 650, - 650, 650, 650, 651, 651, 651, 651, 651, 651, 652, 652, 651, 651, 652, - 652, 651, 651, 82, 650, 650, 650, 651, 650, 650, 650, 650, 650, 650, 650, - 650, 651, 652, 82, 82, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, - 82, 82, 654, 655, 655, 655, 649, 314, 314, 314, 314, 314, 314, 323, 323, - 323, 314, 315, 316, 315, 314, 314, 656, 656, 656, 656, 656, 656, 656, - 656, 657, 656, 657, 657, 658, 656, 656, 657, 657, 656, 656, 656, 656, - 656, 657, 657, 656, 657, 656, 82, 82, 82, 82, 82, 82, 82, 82, 656, 656, - 659, 660, 660, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, - 662, 663, 663, 662, 662, 664, 664, 661, 665, 665, 662, 666, 82, 82, 331, - 331, 331, 331, 331, 331, 82, 57, 57, 57, 614, 60, 60, 60, 60, 57, 57, 57, - 57, 57, 80, 82, 82, 338, 338, 338, 338, 338, 338, 338, 338, 661, 661, - 661, 662, 662, 663, 662, 662, 663, 662, 662, 664, 662, 666, 82, 82, 667, - 667, 667, 667, 667, 667, 667, 667, 667, 667, 82, 82, 82, 82, 82, 82, 668, - 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, - 669, 669, 669, 669, 669, 668, 669, 669, 669, 669, 669, 669, 669, 82, 82, - 82, 82, 329, 329, 329, 329, 329, 329, 329, 82, 82, 82, 82, 330, 330, 330, - 330, 330, 330, 330, 330, 330, 82, 82, 82, 82, 670, 670, 670, 670, 670, - 670, 670, 670, 671, 671, 671, 671, 671, 671, 671, 671, 593, 593, 594, - 594, 594, 594, 594, 594, 57, 57, 57, 57, 57, 57, 57, 82, 82, 82, 82, 102, - 102, 102, 102, 102, 82, 82, 82, 82, 82, 130, 672, 130, 130, 673, 130, - 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 82, 130, 130, - 130, 130, 130, 82, 130, 82, 130, 130, 82, 130, 130, 82, 130, 130, 147, - 147, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, - 674, 674, 674, 82, 82, 82, 82, 82, 82, 82, 82, 82, 147, 147, 147, 147, - 147, 147, 147, 147, 147, 147, 147, 675, 471, 82, 82, 147, 147, 147, 147, - 147, 147, 147, 147, 147, 147, 136, 139, 82, 82, 676, 676, 676, 676, 676, - 676, 676, 676, 677, 557, 557, 677, 677, 678, 678, 563, 564, 679, 82, 82, - 82, 82, 82, 82, 97, 97, 97, 97, 97, 97, 97, 157, 157, 157, 157, 157, 157, - 157, 96, 96, 558, 570, 570, 680, 680, 563, 564, 563, 564, 563, 564, 563, - 564, 563, 564, 563, 564, 563, 564, 563, 564, 558, 558, 563, 564, 558, - 558, 558, 558, 680, 680, 680, 681, 558, 681, 82, 581, 682, 678, 678, 570, - 524, 525, 524, 525, 524, 525, 683, 558, 558, 684, 685, 686, 686, 687, 82, - 558, 688, 689, 558, 82, 82, 82, 82, 147, 147, 147, 147, 147, 82, 82, 493, - 82, 690, 691, 692, 693, 694, 691, 691, 695, 696, 691, 697, 698, 699, 698, - 700, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 702, 703, 704, - 705, 704, 690, 691, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, - 706, 706, 706, 706, 706, 706, 706, 706, 695, 691, 696, 707, 708, 707, - 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, - 709, 709, 709, 709, 695, 705, 696, 705, 695, 696, 710, 711, 712, 710, - 713, 714, 715, 715, 715, 715, 715, 715, 715, 715, 715, 716, 714, 714, - 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, - 714, 714, 714, 714, 714, 717, 717, 718, 718, 718, 718, 718, 718, 718, - 718, 718, 718, 718, 718, 718, 718, 718, 82, 82, 82, 718, 718, 718, 718, - 718, 718, 82, 82, 718, 718, 718, 82, 82, 82, 719, 693, 705, 707, 720, - 693, 693, 82, 721, 722, 722, 722, 722, 721, 721, 82, 82, 723, 723, 723, - 724, 508, 82, 82, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, - 725, 82, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 82, 725, 725, - 725, 82, 725, 725, 82, 725, 725, 725, 725, 725, 725, 725, 82, 82, 725, - 725, 725, 82, 82, 82, 82, 82, 199, 373, 199, 82, 82, 82, 82, 620, 620, - 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 82, 82, 82, 313, - 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 727, - 727, 727, 727, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, 728, - 728, 728, 728, 728, 728, 728, 727, 727, 728, 729, 729, 82, 41, 41, 41, - 41, 82, 82, 82, 82, 728, 82, 82, 82, 82, 82, 82, 82, 313, 313, 313, 313, - 313, 157, 82, 82, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, 730, - 730, 730, 82, 82, 82, 731, 731, 731, 731, 731, 731, 731, 731, 731, 82, - 82, 82, 82, 82, 82, 82, 157, 500, 500, 500, 500, 500, 500, 500, 500, 500, - 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 82, 82, 82, 82, 732, - 732, 732, 732, 732, 732, 732, 732, 733, 733, 733, 733, 82, 82, 82, 82, - 734, 734, 734, 734, 734, 734, 734, 734, 734, 735, 734, 734, 734, 734, - 734, 734, 734, 734, 735, 82, 82, 82, 82, 82, 736, 736, 736, 736, 736, - 736, 736, 736, 736, 736, 736, 736, 736, 736, 737, 737, 737, 737, 737, 82, - 82, 82, 82, 82, 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, 738, - 738, 738, 738, 82, 739, 740, 740, 740, 740, 740, 740, 740, 740, 740, 740, - 740, 740, 82, 82, 82, 82, 741, 742, 742, 742, 742, 742, 82, 82, 743, 743, - 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 744, 744, - 745, 745, 745, 745, 745, 745, 745, 745, 746, 746, 746, 746, 746, 746, - 746, 746, 746, 746, 746, 746, 746, 746, 82, 82, 747, 747, 747, 747, 747, - 747, 747, 747, 747, 747, 82, 82, 82, 82, 82, 82, 748, 748, 748, 748, 748, - 748, 748, 748, 748, 748, 748, 748, 82, 82, 82, 82, 749, 749, 749, 749, - 749, 749, 749, 749, 749, 749, 749, 749, 82, 82, 82, 82, 750, 750, 750, - 750, 750, 750, 750, 750, 751, 751, 751, 751, 751, 751, 751, 751, 751, - 751, 751, 751, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 752, 753, 753, - 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 753, 82, 753, - 753, 753, 753, 753, 753, 82, 82, 754, 754, 754, 754, 754, 754, 82, 82, - 754, 82, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, - 754, 754, 754, 754, 754, 754, 754, 82, 754, 754, 82, 82, 82, 754, 82, 82, - 754, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, - 755, 82, 756, 757, 757, 757, 757, 757, 757, 757, 757, 758, 758, 758, 758, - 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 759, 759, 760, - 760, 760, 760, 760, 760, 760, 761, 761, 761, 761, 761, 761, 761, 761, - 761, 761, 761, 761, 761, 761, 761, 82, 82, 82, 82, 82, 82, 82, 82, 762, - 762, 762, 762, 762, 762, 762, 762, 762, 763, 763, 763, 763, 763, 763, - 763, 763, 763, 763, 763, 82, 763, 763, 82, 82, 82, 82, 82, 764, 764, 764, - 764, 764, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, - 765, 765, 766, 766, 766, 766, 766, 766, 82, 82, 82, 767, 768, 768, 768, - 768, 768, 768, 768, 768, 768, 768, 82, 82, 82, 82, 82, 769, 770, 770, - 770, 770, 770, 770, 770, 770, 771, 771, 771, 771, 771, 771, 771, 771, 82, - 82, 82, 82, 772, 772, 771, 771, 772, 772, 772, 772, 772, 772, 772, 772, - 82, 82, 772, 772, 772, 772, 772, 772, 773, 774, 774, 774, 82, 774, 774, - 82, 82, 82, 82, 82, 774, 775, 774, 776, 773, 773, 773, 773, 82, 773, 773, - 773, 82, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, - 773, 773, 773, 773, 773, 773, 82, 82, 82, 82, 776, 777, 775, 82, 82, 82, - 82, 778, 779, 779, 779, 779, 779, 779, 779, 779, 780, 780, 780, 780, 780, - 780, 780, 780, 781, 82, 82, 82, 82, 82, 82, 82, 782, 782, 782, 782, 782, - 782, 782, 782, 782, 782, 782, 782, 782, 783, 783, 784, 785, 785, 785, - 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 786, 786, 786, 787, - 787, 787, 787, 787, 787, 787, 787, 788, 787, 787, 787, 787, 787, 787, - 787, 787, 787, 787, 787, 787, 789, 790, 82, 82, 82, 82, 791, 791, 791, - 791, 791, 792, 792, 792, 792, 792, 792, 793, 82, 794, 794, 794, 794, 794, - 794, 794, 794, 794, 794, 794, 794, 794, 794, 82, 82, 82, 795, 795, 795, - 795, 795, 795, 795, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, - 796, 796, 796, 796, 82, 82, 797, 797, 797, 797, 797, 797, 797, 797, 798, - 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 82, 82, 82, 82, 82, - 799, 799, 799, 799, 799, 799, 799, 799, 800, 800, 800, 800, 800, 800, - 800, 800, 800, 800, 82, 82, 82, 82, 82, 82, 82, 801, 801, 801, 801, 82, - 82, 82, 82, 802, 802, 802, 802, 802, 802, 802, 803, 803, 803, 803, 803, - 803, 803, 803, 803, 82, 82, 82, 82, 82, 82, 82, 804, 804, 804, 804, 804, - 804, 804, 804, 804, 804, 804, 82, 82, 82, 82, 82, 805, 805, 805, 805, - 805, 805, 805, 805, 805, 805, 805, 82, 82, 82, 82, 82, 82, 82, 806, 806, - 806, 806, 806, 806, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, - 807, 807, 807, 807, 807, 82, 808, 809, 808, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 811, 812, 812, 813, 813, 813, 813, - 813, 82, 82, 82, 82, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, - 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 815, 815, 815, 815, - 815, 815, 815, 815, 815, 815, 82, 82, 82, 82, 82, 82, 82, 811, 816, 816, - 817, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, 818, - 817, 817, 817, 816, 816, 816, 816, 817, 817, 819, 820, 821, 821, 822, - 823, 823, 823, 823, 82, 82, 82, 82, 82, 82, 824, 824, 824, 824, 824, 824, - 824, 824, 824, 82, 82, 82, 82, 82, 82, 82, 825, 825, 825, 825, 825, 825, - 825, 825, 825, 825, 82, 82, 82, 82, 82, 82, 826, 826, 826, 827, 827, 827, - 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, - 827, 827, 827, 828, 828, 828, 828, 828, 829, 828, 828, 828, 828, 828, - 828, 830, 830, 82, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 832, - 832, 832, 832, 82, 82, 82, 82, 833, 833, 833, 833, 833, 833, 833, 833, - 833, 833, 833, 834, 835, 836, 833, 82, 837, 837, 838, 839, 839, 839, 839, - 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 838, 838, - 838, 837, 837, 837, 837, 837, 837, 837, 837, 837, 838, 840, 839, 839, - 839, 839, 841, 841, 842, 841, 842, 843, 837, 837, 842, 82, 82, 844, 844, - 844, 844, 844, 844, 844, 844, 844, 844, 839, 845, 839, 841, 841, 841, 82, - 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, 846, - 846, 846, 846, 846, 846, 846, 82, 82, 82, 847, 847, 847, 847, 847, 847, - 847, 847, 847, 847, 82, 847, 847, 847, 847, 847, 847, 847, 847, 847, 848, - 848, 848, 849, 849, 849, 848, 848, 849, 850, 851, 849, 852, 852, 853, - 852, 852, 853, 849, 82, 854, 854, 854, 854, 854, 854, 854, 82, 854, 82, - 854, 854, 854, 854, 82, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, - 854, 854, 854, 854, 854, 82, 854, 854, 855, 82, 82, 82, 82, 82, 82, 856, - 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - 857, 858, 858, 858, 857, 857, 857, 857, 857, 857, 859, 860, 82, 82, 82, - 82, 82, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 82, 82, 82, 82, - 82, 82, 862, 862, 863, 863, 82, 864, 864, 864, 864, 864, 864, 864, 864, - 82, 82, 864, 864, 82, 82, 864, 864, 864, 864, 864, 864, 864, 864, 864, - 864, 864, 864, 864, 864, 82, 864, 864, 864, 864, 864, 864, 864, 82, 864, - 864, 82, 864, 864, 864, 864, 864, 82, 82, 865, 864, 863, 863, 862, 863, - 863, 863, 863, 82, 82, 863, 863, 82, 82, 863, 863, 866, 82, 82, 864, 82, - 82, 82, 82, 82, 82, 863, 82, 82, 82, 82, 82, 864, 864, 864, 864, 864, - 863, 863, 82, 82, 867, 867, 867, 867, 867, 867, 867, 82, 82, 82, 868, - 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 869, 869, - 869, 870, 870, 870, 870, 870, 870, 870, 870, 869, 869, 871, 870, 870, - 869, 872, 868, 868, 868, 868, 873, 873, 873, 873, 874, 875, 875, 875, - 875, 875, 875, 875, 875, 875, 875, 82, 873, 82, 874, 82, 82, 876, 876, - 876, 876, 876, 876, 876, 876, 877, 877, 877, 878, 878, 878, 878, 878, - 878, 877, 878, 877, 877, 877, 877, 878, 878, 877, 879, 880, 876, 876, - 881, 876, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 82, 82, 82, - 82, 82, 82, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, - 883, 883, 883, 884, 884, 884, 885, 885, 885, 885, 82, 82, 884, 884, 884, - 884, 885, 885, 884, 886, 887, 888, 889, 889, 890, 890, 891, 891, 891, - 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, - 889, 883, 883, 883, 883, 885, 885, 82, 82, 892, 892, 892, 892, 892, 892, - 892, 892, 893, 893, 893, 894, 894, 894, 894, 894, 894, 894, 894, 893, - 893, 894, 893, 895, 894, 896, 896, 897, 892, 82, 82, 82, 898, 898, 898, - 898, 898, 898, 898, 898, 898, 898, 82, 82, 82, 82, 82, 82, 899, 899, 899, - 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 82, 82, 82, 900, 900, - 900, 900, 900, 900, 900, 900, 900, 900, 900, 901, 902, 901, 902, 902, - 901, 901, 901, 901, 901, 901, 903, 904, 905, 905, 905, 905, 905, 905, - 905, 905, 905, 905, 82, 82, 82, 82, 82, 82, 906, 906, 906, 906, 906, 906, - 906, 906, 906, 906, 82, 82, 82, 907, 907, 907, 908, 908, 907, 907, 907, - 907, 908, 907, 907, 907, 907, 909, 82, 82, 82, 82, 910, 910, 910, 910, - 910, 910, 910, 910, 910, 910, 911, 911, 912, 912, 912, 913, 914, 914, - 914, 914, 914, 914, 914, 914, 915, 915, 915, 915, 915, 915, 915, 915, - 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 917, 917, 917, 917, - 917, 917, 917, 917, 917, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 918, 919, 919, 919, 919, 919, 919, 919, 919, 919, 82, 82, 82, 82, 82, 82, - 82, 920, 920, 920, 920, 920, 920, 920, 920, 920, 82, 920, 920, 920, 920, - 920, 920, 920, 920, 920, 920, 920, 920, 920, 921, 922, 922, 922, 922, - 922, 922, 922, 82, 922, 922, 922, 922, 922, 922, 921, 923, 920, 924, 924, - 924, 924, 924, 82, 82, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, - 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, - 926, 926, 926, 926, 926, 82, 82, 82, 927, 928, 929, 929, 929, 929, 929, - 929, 929, 929, 929, 929, 929, 929, 929, 929, 82, 82, 930, 930, 930, 930, - 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 82, 931, 930, 930, 930, - 930, 930, 930, 930, 931, 930, 930, 931, 930, 930, 82, 932, 932, 932, 932, - 932, 932, 932, 932, 932, 932, 82, 82, 82, 82, 82, 82, 933, 933, 933, 933, - 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 82, 934, 934, 934, - 934, 934, 82, 82, 82, 932, 932, 932, 932, 82, 82, 82, 82, 935, 935, 935, - 935, 935, 935, 935, 935, 936, 936, 936, 937, 937, 937, 935, 935, 935, - 935, 937, 935, 935, 935, 936, 937, 936, 937, 935, 935, 935, 935, 935, - 935, 935, 936, 937, 937, 935, 935, 935, 935, 935, 935, 935, 935, 935, - 935, 935, 82, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, - 938, 938, 939, 940, 938, 938, 938, 938, 938, 938, 938, 82, 609, 82, 82, - 82, 82, 82, 82, 82, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, - 941, 941, 941, 941, 941, 82, 942, 942, 942, 942, 942, 942, 942, 942, 942, - 942, 82, 82, 82, 82, 943, 943, 944, 944, 944, 944, 944, 944, 944, 944, - 944, 944, 944, 944, 944, 944, 82, 82, 945, 945, 945, 945, 945, 946, 82, - 82, 947, 947, 947, 947, 947, 947, 947, 947, 948, 948, 948, 948, 948, 948, - 948, 949, 949, 949, 950, 950, 951, 951, 951, 951, 952, 952, 952, 952, - 949, 951, 82, 82, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 82, - 954, 954, 954, 954, 954, 954, 954, 82, 947, 947, 947, 947, 947, 82, 82, - 82, 82, 82, 947, 947, 947, 955, 955, 955, 955, 955, 955, 955, 955, 955, - 955, 955, 955, 955, 82, 82, 82, 955, 956, 956, 956, 956, 956, 956, 956, - 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, - 956, 82, 82, 82, 82, 82, 82, 82, 82, 957, 957, 957, 957, 958, 958, 958, - 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 959, 82, 82, 82, 82, - 82, 82, 82, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, - 960, 82, 82, 82, 960, 960, 960, 82, 82, 82, 82, 82, 580, 575, 82, 82, 82, - 82, 82, 82, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 82, - 82, 82, 82, 82, 961, 961, 961, 961, 961, 82, 82, 82, 961, 82, 82, 82, 82, - 82, 82, 82, 961, 961, 82, 82, 962, 963, 964, 965, 499, 499, 499, 499, 82, - 82, 82, 82, 313, 313, 313, 313, 313, 313, 82, 82, 313, 313, 313, 313, - 313, 313, 313, 82, 82, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 966, 966, 447, 447, 447, 313, 313, 313, 967, 966, 966, 966, - 966, 966, 499, 499, 499, 499, 499, 499, 499, 499, 157, 157, 157, 157, - 157, 157, 157, 157, 313, 313, 97, 97, 97, 97, 97, 157, 157, 313, 313, - 313, 313, 313, 313, 97, 97, 97, 97, 313, 313, 313, 82, 82, 82, 82, 82, - 82, 82, 728, 728, 968, 968, 968, 728, 82, 82, 620, 620, 82, 82, 82, 82, - 82, 82, 506, 506, 506, 506, 506, 506, 506, 506, 506, 506, 50, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 506, 506, 506, - 506, 506, 506, 506, 506, 506, 506, 50, 50, 50, 50, 50, 50, 50, 82, 50, - 50, 50, 50, 50, 50, 506, 82, 506, 506, 82, 82, 506, 82, 82, 506, 506, 82, - 82, 506, 506, 506, 506, 82, 506, 506, 50, 50, 82, 50, 82, 50, 50, 50, 50, - 50, 50, 50, 82, 50, 50, 50, 50, 50, 50, 50, 506, 506, 82, 506, 506, 506, - 506, 82, 82, 506, 506, 506, 506, 506, 506, 506, 506, 82, 506, 506, 506, - 506, 506, 506, 506, 82, 50, 50, 506, 506, 82, 506, 506, 506, 506, 82, - 506, 506, 506, 506, 506, 82, 506, 82, 82, 82, 506, 506, 506, 506, 506, - 506, 506, 82, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 82, 82, - 506, 969, 50, 50, 50, 50, 50, 50, 50, 50, 50, 513, 50, 50, 50, 50, 50, - 50, 506, 506, 506, 506, 506, 506, 506, 506, 506, 969, 50, 50, 50, 50, 50, - 50, 50, 50, 50, 513, 50, 50, 506, 506, 506, 506, 506, 969, 50, 50, 50, - 50, 50, 50, 50, 50, 50, 513, 50, 50, 50, 50, 50, 50, 506, 506, 506, 506, - 506, 506, 506, 506, 506, 969, 50, 513, 50, 50, 50, 50, 50, 50, 50, 50, - 506, 50, 82, 82, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 971, - 971, 971, 971, 971, 971, 971, 971, 972, 972, 972, 972, 972, 972, 972, - 972, 972, 972, 972, 972, 972, 972, 972, 971, 971, 971, 971, 972, 972, - 972, 972, 972, 972, 972, 972, 972, 972, 971, 971, 971, 971, 971, 971, - 971, 971, 972, 971, 971, 971, 971, 971, 971, 972, 971, 971, 973, 973, - 973, 973, 974, 82, 82, 82, 82, 82, 82, 82, 972, 972, 972, 972, 972, 82, - 972, 972, 972, 972, 972, 972, 972, 975, 975, 975, 975, 975, 975, 975, 82, - 975, 975, 975, 975, 975, 975, 975, 975, 975, 82, 82, 975, 975, 975, 975, - 975, 975, 975, 82, 975, 975, 82, 975, 975, 975, 975, 975, 82, 82, 82, 82, - 82, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 82, - 82, 977, 977, 977, 977, 977, 977, 977, 977, 977, 978, 978, 978, 978, 978, - 978, 978, 82, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 980, 980, - 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, - 980, 980, 981, 981, 981, 981, 981, 981, 982, 82, 82, 82, 82, 82, 983, - 983, 983, 983, 983, 983, 983, 983, 983, 983, 82, 82, 82, 82, 984, 984, - 147, 147, 147, 147, 82, 147, 147, 147, 82, 147, 147, 82, 147, 82, 82, - 147, 82, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 82, 147, 147, - 147, 147, 82, 147, 82, 147, 82, 82, 82, 82, 82, 82, 147, 82, 82, 82, 82, - 147, 82, 147, 82, 147, 82, 147, 147, 147, 82, 147, 82, 147, 82, 147, 82, - 147, 82, 147, 147, 147, 147, 82, 147, 82, 147, 147, 82, 147, 147, 147, - 147, 147, 147, 147, 147, 147, 82, 82, 82, 82, 82, 147, 147, 147, 82, 147, - 147, 147, 133, 133, 82, 82, 82, 82, 82, 82, 527, 527, 527, 527, 523, 527, - 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, - 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 527, 527, - 527, 527, 527, 527, 527, 985, 985, 527, 527, 527, 527, 527, 527, 527, - 527, 527, 527, 527, 527, 527, 527, 523, 527, 527, 527, 527, 527, 527, - 985, 985, 48, 48, 48, 516, 516, 985, 985, 985, 528, 528, 528, 528, 528, - 528, 313, 985, 528, 528, 41, 41, 985, 985, 985, 985, 528, 528, 528, 528, - 528, 528, 986, 528, 528, 986, 986, 986, 986, 986, 986, 986, 986, 986, - 986, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 985, 985, 985, - 985, 985, 985, 985, 985, 985, 987, 987, 987, 987, 987, 987, 987, 987, - 987, 987, 988, 586, 586, 985, 985, 985, 985, 985, 586, 586, 586, 586, - 985, 985, 985, 985, 586, 985, 985, 985, 985, 985, 985, 985, 586, 586, - 985, 985, 985, 985, 985, 985, 523, 527, 527, 527, 527, 527, 527, 527, - 527, 527, 527, 527, 527, 523, 523, 523, 523, 523, 523, 523, 523, 523, - 527, 523, 523, 523, 523, 523, 523, 527, 523, 523, 523, 523, 523, 523, - 523, 534, 523, 523, 523, 523, 523, 523, 527, 527, 527, 527, 527, 527, - 527, 527, 41, 41, 527, 527, 523, 523, 523, 523, 523, 526, 526, 523, 523, - 523, 523, 523, 526, 523, 523, 523, 523, 523, 523, 534, 534, 523, 523, - 523, 523, 523, 534, 532, 527, 527, 527, 523, 523, 527, 527, 527, 523, - 527, 527, 527, 523, 523, 523, 989, 989, 989, 989, 989, 523, 523, 523, - 523, 523, 523, 523, 527, 523, 527, 534, 534, 523, 523, 534, 534, 534, - 534, 534, 534, 534, 534, 534, 534, 534, 523, 523, 523, 523, 523, 523, - 523, 523, 523, 523, 523, 523, 523, 534, 534, 534, 534, 523, 523, 523, - 523, 534, 523, 534, 523, 523, 523, 534, 523, 523, 523, 523, 534, 534, - 534, 523, 534, 534, 534, 526, 523, 526, 523, 526, 523, 523, 523, 523, - 523, 534, 523, 523, 523, 523, 526, 523, 526, 526, 523, 523, 523, 523, - 523, 523, 523, 523, 523, 523, 527, 527, 523, 526, 526, 526, 526, 526, - 526, 526, 523, 523, 523, 523, 523, 523, 523, 523, 526, 526, 526, 526, - 526, 526, 523, 523, 523, 523, 523, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 41, 41, 41, 41, 527, 523, 523, 523, 523, 527, - 527, 527, 527, 527, 527, 532, 527, 527, 527, 527, 534, 527, 527, 527, - 527, 527, 532, 527, 527, 527, 527, 534, 534, 527, 527, 527, 527, 527, 41, - 41, 41, 41, 41, 41, 41, 41, 527, 527, 527, 527, 41, 41, 527, 523, 523, - 523, 523, 523, 523, 523, 523, 523, 523, 534, 534, 534, 523, 523, 523, - 534, 534, 534, 534, 534, 41, 41, 41, 41, 41, 41, 536, 536, 536, 990, 990, - 990, 41, 41, 41, 41, 523, 523, 523, 534, 523, 523, 523, 523, 523, 523, - 523, 523, 534, 534, 534, 523, 534, 523, 523, 523, 523, 523, 527, 527, - 523, 523, 523, 985, 985, 985, 985, 985, 527, 527, 527, 523, 523, 985, - 985, 985, 527, 527, 527, 527, 523, 523, 523, 985, 41, 41, 41, 41, 985, - 985, 985, 985, 41, 41, 41, 41, 41, 985, 985, 985, 41, 41, 985, 985, 985, - 985, 985, 985, 41, 41, 41, 41, 41, 41, 985, 985, 534, 534, 534, 534, 534, - 534, 534, 985, 523, 523, 523, 523, 523, 523, 534, 523, 534, 985, 985, - 534, 534, 534, 534, 534, 534, 534, 523, 523, 534, 534, 534, 985, 523, - 523, 523, 523, 985, 985, 985, 985, 523, 523, 523, 523, 523, 523, 523, - 985, 523, 523, 985, 985, 985, 985, 985, 985, 523, 985, 985, 985, 985, - 985, 985, 985, 985, 985, 985, 985, 985, 985, 82, 82, 593, 593, 593, 593, - 593, 593, 593, 594, 593, 593, 593, 593, 593, 594, 594, 594, 594, 594, - 594, 594, 594, 594, 82, 82, 82, 499, 82, 82, 82, 82, 82, 82, 499, 499, - 499, 499, 499, 499, 499, 499, 671, 671, 671, 671, 671, 671, 82, 82, + 22, 22, 22, 22, 22, 22, 22, 22, 19, 23, 24, 24, 24, 10, 15, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 16, 26, 17, + 27, 28, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 16, 30, 31, 24, 1, 1, 1, 1, 1, 1, 32, 1, 1, 33, 34, 35, 13, + 36, 13, 37, 38, 39, 40, 41, 42, 24, 43, 44, 27, 45, 46, 47, 47, 48, 49, + 38, 38, 39, 47, 41, 50, 51, 51, 51, 34, 52, 52, 52, 52, 52, 52, 53, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 52, 54, 53, 52, + 52, 52, 52, 52, 53, 55, 55, 55, 56, 56, 56, 56, 55, 56, 55, 55, 55, 56, + 55, 55, 56, 56, 55, 56, 55, 55, 56, 56, 56, 54, 55, 55, 55, 56, 55, 56, + 55, 56, 52, 55, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, 52, 56, + 52, 55, 52, 55, 52, 56, 52, 56, 52, 56, 52, 55, 52, 56, 52, 56, 52, 56, + 52, 56, 52, 56, 53, 55, 52, 55, 53, 55, 52, 56, 52, 56, 55, 52, 56, 52, + 56, 52, 56, 53, 55, 53, 55, 52, 55, 52, 56, 52, 55, 55, 53, 55, 52, 55, + 52, 56, 52, 56, 53, 55, 52, 56, 52, 56, 52, 52, 56, 52, 56, 52, 56, 56, + 56, 52, 52, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 56, 52, 52, 52, 52, + 56, 52, 52, 56, 52, 52, 52, 56, 56, 56, 52, 52, 56, 52, 52, 56, 52, 56, + 52, 56, 52, 52, 56, 52, 56, 56, 52, 56, 52, 52, 56, 52, 52, 52, 56, 52, + 56, 52, 52, 56, 56, 57, 52, 56, 56, 56, 57, 57, 57, 57, 52, 58, 56, 52, + 58, 56, 52, 58, 56, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, 55, 52, + 55, 52, 55, 56, 52, 56, 56, 52, 58, 56, 52, 56, 52, 52, 52, 56, 52, 56, + 56, 56, 56, 56, 56, 56, 52, 52, 56, 52, 52, 56, 56, 52, 56, 52, 52, 52, + 52, 56, 56, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 57, 56, 56, 56, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, + 60, 61, 61, 61, 61, 61, 61, 61, 62, 62, 63, 62, 60, 64, 65, 64, 64, 64, + 65, 64, 60, 60, 66, 61, 62, 62, 62, 62, 62, 62, 39, 39, 39, 39, 62, 39, + 62, 48, 59, 59, 59, 59, 59, 62, 62, 62, 62, 62, 67, 67, 60, 62, 61, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 69, 70, 70, 70, 70, 69, 71, 70, 70, 70, 70, 70, 72, 72, 70, + 70, 70, 70, 72, 72, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 73, 73, + 73, 73, 73, 70, 70, 70, 70, 68, 68, 68, 68, 68, 68, 68, 68, 74, 68, 70, + 70, 70, 68, 68, 68, 70, 70, 75, 68, 68, 68, 70, 70, 70, 70, 68, 69, 70, + 70, 68, 76, 77, 77, 76, 77, 77, 76, 68, 68, 68, 68, 68, 78, 79, 78, 79, + 60, 80, 78, 79, 81, 81, 82, 79, 79, 79, 83, 78, 81, 81, 81, 81, 80, 62, + 78, 84, 78, 78, 78, 81, 78, 81, 78, 78, 79, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 81, 85, 85, 85, 85, 85, 85, 85, + 78, 78, 79, 79, 79, 79, 79, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 79, 86, 86, 86, 86, 86, 86, 86, 79, 79, 79, 79, + 79, 78, 79, 79, 78, 78, 78, 79, 79, 79, 78, 79, 78, 79, 78, 79, 78, 79, + 78, 79, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 87, 88, 79, 79, + 79, 79, 78, 79, 89, 78, 79, 78, 78, 79, 79, 78, 78, 78, 90, 91, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, + 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 93, 92, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, + 94, 95, 95, 96, 96, 95, 97, 97, 90, 93, 90, 93, 90, 93, 90, 90, 93, 90, + 93, 90, 93, 90, 93, 90, 93, 90, 93, 90, 93, 93, 81, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 81, + 81, 99, 100, 100, 100, 100, 100, 100, 81, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 81, 102, 103, 81, 81, 104, + 104, 105, 81, 106, 107, 107, 107, 107, 106, 107, 107, 107, 108, 106, 107, + 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 107, 107, 106, + 107, 107, 108, 109, 107, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 119, 120, 121, 122, 123, 124, 125, 126, 127, 125, 107, 106, 128, + 118, 81, 81, 81, 81, 81, 81, 81, 81, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 81, 81, 81, 81, 81, 129, 129, 129, 125, 125, 81, 81, + 81, 130, 130, 130, 130, 130, 131, 132, 132, 133, 134, 134, 135, 136, 137, + 138, 138, 139, 139, 139, 139, 139, 139, 139, 139, 140, 141, 142, 143, + 144, 81, 145, 143, 146, 146, 146, 146, 146, 146, 146, 146, 147, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 148, 149, 150, 151, 152, 153, + 154, 155, 96, 96, 156, 157, 139, 139, 139, 139, 139, 157, 139, 139, 157, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 134, 159, 159, 160, + 146, 146, 161, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 145, 146, 139, 139, 139, 139, 139, 139, 139, 131, 138, 139, 139, 139, + 139, 157, 139, 162, 162, 139, 139, 138, 157, 139, 139, 157, 146, 146, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 146, 146, 146, 164, + 164, 146, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 81, 166, 167, 168, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 169, 170, 169, 169, 170, 169, 169, 170, 170, + 170, 169, 170, 170, 169, 170, 169, 169, 169, 170, 169, 170, 169, 170, + 169, 170, 169, 169, 81, 81, 167, 167, 167, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 171, 81, 81, 81, 81, 81, 81, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, + 175, 175, 176, 175, 177, 177, 178, 179, 180, 181, 177, 81, 81, 81, 81, + 81, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 183, 183, 183, 183, 184, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 184, 183, 183, 183, 184, 183, 183, 183, 183, 183, 81, 81, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 81, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 81, 81, 188, 81, 167, + 167, 167, 81, 81, 81, 81, 81, 146, 146, 146, 146, 146, 81, 146, 146, 146, + 146, 146, 146, 146, 146, 81, 81, 81, 81, 81, 81, 139, 139, 139, 139, 139, + 139, 131, 157, 139, 139, 157, 139, 139, 157, 139, 139, 139, 157, 157, + 157, 189, 190, 191, 139, 139, 139, 157, 139, 139, 157, 157, 139, 139, + 139, 139, 139, 192, 192, 192, 193, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 192, 193, 195, 194, 193, 193, 193, + 192, 192, 192, 192, 192, 192, 192, 192, 193, 193, 193, 193, 196, 193, + 193, 194, 96, 156, 197, 197, 192, 192, 192, 194, 194, 192, 192, 198, 198, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 200, 201, 194, 194, + 194, 194, 194, 194, 202, 203, 204, 204, 81, 202, 202, 202, 202, 202, 202, + 202, 202, 81, 81, 202, 202, 81, 81, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 81, 202, 202, 202, 202, 202, 202, 202, + 81, 202, 81, 81, 81, 202, 202, 202, 202, 81, 81, 205, 202, 204, 204, 204, + 203, 203, 203, 203, 81, 81, 204, 204, 81, 81, 204, 204, 206, 202, 81, 81, + 81, 81, 81, 81, 81, 81, 204, 81, 81, 81, 81, 202, 202, 81, 202, 202, 202, + 203, 203, 81, 81, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 202, + 202, 208, 208, 209, 209, 209, 209, 209, 210, 211, 212, 202, 213, 81, 81, + 81, 214, 214, 215, 81, 216, 216, 216, 216, 216, 216, 81, 81, 81, 81, 216, + 216, 81, 81, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 81, 216, 216, 216, 216, 216, 216, 216, 81, 216, 216, 81, 216, + 216, 81, 216, 216, 81, 81, 217, 81, 215, 215, 215, 214, 214, 81, 81, 81, + 81, 214, 214, 81, 81, 214, 214, 218, 81, 81, 81, 214, 81, 81, 81, 81, 81, + 81, 81, 216, 216, 216, 216, 81, 216, 81, 81, 81, 81, 81, 81, 81, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 214, 214, 216, 216, 216, + 214, 81, 81, 81, 220, 220, 221, 81, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 81, 222, 222, 222, 81, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 81, 222, 222, 222, 222, 222, 222, 222, 81, + 222, 222, 81, 222, 222, 222, 222, 222, 81, 81, 223, 222, 221, 221, 221, + 220, 220, 220, 220, 220, 81, 220, 220, 221, 81, 221, 221, 224, 81, 81, + 222, 81, 81, 81, 81, 81, 81, 81, 222, 222, 220, 220, 81, 81, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 226, 227, 81, 81, 81, 81, 81, 81, + 81, 222, 220, 220, 220, 220, 220, 220, 81, 228, 229, 229, 81, 230, 230, + 230, 230, 230, 230, 230, 230, 81, 81, 230, 230, 81, 81, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 81, 230, 230, 230, + 230, 230, 230, 230, 81, 230, 230, 81, 230, 230, 230, 230, 230, 81, 81, + 231, 230, 229, 228, 229, 228, 228, 228, 228, 81, 81, 229, 229, 81, 81, + 229, 229, 232, 81, 81, 81, 81, 81, 81, 81, 81, 228, 229, 81, 81, 81, 81, + 230, 230, 81, 230, 230, 230, 228, 228, 81, 81, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 234, 230, 235, 235, 235, 235, 235, 235, 81, 81, + 236, 237, 81, 237, 237, 237, 237, 237, 237, 81, 81, 81, 237, 237, 237, + 81, 237, 237, 237, 237, 81, 81, 81, 237, 237, 81, 237, 81, 237, 237, 81, + 81, 81, 237, 237, 81, 81, 81, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 81, 81, 81, 81, 238, 238, 236, 238, 238, 81, 81, 81, 238, 238, + 238, 81, 238, 238, 238, 239, 81, 81, 237, 81, 81, 81, 81, 81, 81, 238, + 81, 81, 81, 81, 81, 81, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 241, 241, 241, 242, 242, 242, 242, 242, 242, 243, 242, 81, 81, 81, 81, + 81, 244, 245, 245, 245, 81, 246, 246, 246, 246, 246, 246, 246, 246, 81, + 246, 246, 246, 81, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 81, 81, 81, 246, 244, 244, 244, 245, 245, 245, + 245, 81, 244, 244, 244, 81, 244, 244, 244, 247, 81, 81, 81, 81, 81, 81, + 81, 248, 249, 81, 246, 246, 246, 81, 81, 81, 81, 81, 246, 246, 244, 244, + 81, 81, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, + 251, 251, 251, 251, 252, 253, 254, 255, 255, 81, 253, 253, 253, 253, 253, + 253, 253, 253, 81, 253, 253, 253, 81, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 81, 253, 253, 253, + 253, 253, 81, 81, 256, 253, 255, 257, 255, 255, 255, 255, 255, 81, 257, + 255, 255, 81, 255, 255, 254, 258, 81, 81, 81, 81, 81, 81, 81, 255, 255, + 81, 81, 81, 81, 81, 81, 81, 253, 81, 253, 253, 254, 254, 81, 81, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 81, 253, 253, 81, 81, 81, + 81, 81, 260, 260, 261, 261, 81, 262, 262, 262, 262, 262, 262, 262, 262, + 81, 262, 262, 262, 81, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, + 262, 262, 262, 262, 262, 262, 262, 263, 263, 262, 261, 261, 261, 260, + 260, 260, 260, 81, 261, 261, 261, 81, 261, 261, 261, 263, 262, 264, 81, + 81, 81, 81, 262, 262, 262, 261, 265, 265, 265, 265, 265, 265, 265, 262, + 262, 262, 260, 260, 81, 81, 266, 266, 266, 266, 266, 266, 266, 266, 266, + 266, 265, 265, 265, 265, 265, 265, 265, 265, 265, 267, 262, 262, 262, + 262, 262, 262, 81, 81, 268, 268, 81, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 81, 81, 81, 269, + 269, 269, 269, 269, 269, 269, 269, 81, 269, 269, 269, 269, 269, 269, 269, + 269, 269, 81, 269, 81, 81, 81, 81, 270, 81, 81, 81, 81, 268, 268, 268, + 271, 271, 271, 81, 271, 81, 268, 268, 268, 268, 268, 268, 268, 268, 81, + 81, 81, 81, 81, 81, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 81, + 81, 268, 268, 273, 81, 81, 81, 81, 274, 274, 274, 274, 274, 274, 274, + 274, 274, 274, 274, 274, 274, 274, 274, 274, 275, 274, 274, 275, 275, + 275, 275, 276, 276, 277, 81, 81, 81, 81, 278, 274, 274, 274, 274, 274, + 274, 279, 275, 280, 280, 280, 280, 275, 275, 275, 281, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 283, 283, 81, 81, 81, 81, 81, 284, + 284, 81, 284, 81, 81, 284, 284, 81, 284, 81, 81, 284, 81, 81, 81, 81, 81, + 81, 284, 284, 284, 284, 81, 284, 284, 284, 284, 284, 284, 284, 81, 284, + 284, 284, 81, 284, 81, 284, 81, 81, 284, 284, 81, 284, 284, 284, 284, + 285, 284, 284, 285, 285, 285, 285, 286, 286, 81, 285, 285, 284, 81, 81, + 284, 284, 284, 284, 284, 81, 287, 81, 288, 288, 288, 288, 285, 285, 81, + 81, 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, 81, 81, 284, 284, + 284, 284, 290, 291, 291, 291, 292, 293, 292, 292, 294, 292, 292, 295, + 294, 296, 296, 296, 296, 296, 294, 297, 296, 297, 297, 297, 298, 298, + 297, 297, 297, 297, 297, 297, 299, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 301, 298, + 297, 298, 297, 302, 303, 304, 303, 304, 305, 305, 290, 290, 290, 290, + 290, 290, 290, 290, 81, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 81, 81, 81, 81, 306, 307, 308, 309, 308, 308, 308, 308, 308, + 307, 307, 307, 307, 308, 310, 307, 308, 311, 311, 312, 295, 311, 311, + 290, 290, 290, 290, 290, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 308, 308, 81, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, + 81, 301, 301, 297, 297, 297, 297, 297, 297, 298, 297, 297, 297, 297, 297, + 297, 81, 297, 297, 292, 292, 295, 292, 293, 313, 313, 313, 313, 294, 294, + 81, 81, 81, 81, 81, 314, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 315, 315, 316, 316, 316, 316, 315, 316, 316, 316, 316, 316, 317, + 315, 318, 318, 315, 315, 316, 316, 314, 319, 319, 319, 319, 319, 319, + 319, 319, 319, 319, 320, 320, 321, 321, 321, 321, 314, 314, 314, 314, + 314, 314, 315, 315, 316, 316, 314, 314, 314, 314, 316, 316, 316, 314, + 315, 315, 315, 314, 314, 315, 315, 315, 315, 315, 315, 315, 314, 314, + 314, 316, 316, 316, 316, 314, 314, 314, 314, 314, 316, 315, 315, 316, + 316, 315, 315, 315, 315, 315, 315, 322, 314, 315, 319, 319, 315, 315, + 315, 316, 323, 323, 324, 324, 324, 324, 324, 324, 324, 324, 324, 324, + 324, 324, 324, 324, 81, 324, 81, 81, 81, 81, 81, 324, 81, 81, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 325, 326, 327, 325, 325, 325, + 328, 328, 328, 328, 328, 328, 328, 328, 329, 329, 329, 329, 329, 329, + 329, 329, 330, 330, 330, 330, 330, 330, 330, 330, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 81, 331, 331, 331, 331, 81, 81, 331, 331, 331, + 331, 331, 331, 331, 81, 331, 331, 331, 81, 81, 332, 332, 332, 333, 334, + 333, 333, 333, 333, 333, 333, 333, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 81, 81, + 81, 336, 336, 336, 336, 336, 336, 336, 336, 336, 336, 81, 81, 81, 81, 81, + 81, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 81, 81, 338, 338, 338, 338, 338, 338, 81, 81, 339, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 341, 341, 340, 342, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 344, 345, 81, 81, 81, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 198, 198, 198, + 347, 347, 347, 346, 346, 346, 346, 346, 346, 346, 346, 81, 81, 81, 81, + 81, 81, 81, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, + 348, 81, 348, 348, 348, 348, 349, 349, 350, 81, 81, 81, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 352, 352, 353, 198, 198, 81, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 355, 81, 81, 81, 81, 356, + 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 356, 81, 356, 356, + 356, 81, 357, 357, 81, 81, 81, 81, 358, 358, 358, 358, 358, 358, 358, + 358, 358, 358, 358, 358, 359, 359, 360, 359, 359, 359, 359, 359, 359, + 359, 360, 360, 360, 360, 360, 360, 360, 360, 359, 360, 360, 359, 359, + 359, 359, 359, 359, 359, 359, 359, 361, 359, 362, 362, 363, 364, 362, + 365, 362, 366, 358, 367, 81, 81, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 81, 81, 81, 81, 81, 81, 369, 369, 369, 369, 369, 369, 369, 369, + 369, 369, 81, 81, 81, 81, 81, 81, 370, 370, 371, 371, 372, 373, 374, 370, + 375, 375, 370, 376, 376, 376, 377, 81, 378, 378, 378, 378, 378, 378, 378, + 378, 378, 378, 81, 81, 81, 81, 81, 81, 379, 379, 379, 379, 379, 379, 379, + 379, 379, 379, 379, 380, 379, 379, 379, 379, 379, 379, 379, 379, 379, + 376, 376, 379, 379, 381, 379, 81, 81, 81, 81, 81, 340, 340, 340, 340, + 340, 340, 81, 81, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 81, 383, 383, 383, 384, 384, 384, 384, 383, 383, 384, + 384, 384, 81, 81, 81, 81, 384, 384, 383, 384, 384, 384, 384, 384, 384, + 385, 386, 387, 81, 81, 81, 81, 388, 81, 81, 81, 389, 389, 390, 390, 390, + 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, + 391, 391, 391, 391, 391, 391, 391, 81, 81, 391, 391, 391, 391, 391, 81, + 81, 81, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 81, + 81, 81, 81, 392, 392, 81, 81, 81, 81, 81, 81, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 394, 81, 81, 81, 395, 395, 396, 396, 396, 396, + 396, 396, 396, 396, 397, 397, 397, 397, 397, 397, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 398, 399, 400, 400, 401, 81, 81, 402, 402, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 404, 405, + 404, 405, 405, 405, 405, 405, 405, 405, 81, 406, 404, 405, 404, 404, 405, + 405, 405, 405, 405, 405, 405, 405, 404, 404, 404, 404, 404, 404, 405, + 405, 407, 407, 407, 407, 407, 407, 407, 407, 81, 81, 408, 409, 409, 409, + 409, 409, 409, 409, 409, 409, 409, 81, 81, 81, 81, 81, 81, 410, 410, 410, + 410, 410, 410, 410, 411, 410, 410, 410, 410, 410, 410, 81, 81, 96, 96, + 96, 96, 96, 156, 156, 156, 156, 156, 156, 96, 96, 156, 412, 81, 413, 413, + 413, 413, 414, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, 415, + 415, 415, 415, 415, 416, 414, 413, 413, 413, 413, 413, 414, 413, 414, + 414, 414, 414, 414, 413, 414, 417, 415, 415, 415, 415, 415, 415, 415, 81, + 81, 81, 81, 418, 418, 418, 418, 418, 418, 418, 418, 418, 418, 419, 419, + 420, 419, 419, 419, 419, 421, 421, 421, 421, 421, 421, 421, 421, 421, + 421, 422, 423, 422, 422, 422, 422, 422, 422, 422, 421, 421, 421, 421, + 421, 421, 421, 421, 421, 81, 81, 81, 424, 424, 425, 426, 426, 426, 426, + 426, 426, 426, 426, 426, 426, 426, 426, 426, 426, 425, 424, 424, 424, + 424, 425, 425, 424, 424, 427, 428, 424, 424, 426, 426, 429, 429, 429, + 429, 429, 429, 429, 429, 429, 429, 426, 426, 426, 426, 426, 426, 430, + 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 431, + 432, 433, 433, 432, 432, 432, 433, 432, 433, 433, 433, 434, 434, 81, 81, + 81, 81, 81, 81, 81, 81, 435, 435, 435, 435, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 437, 437, 437, 437, 437, 437, 437, 437, + 438, 438, 438, 438, 438, 438, 438, 438, 437, 437, 438, 439, 81, 81, 81, + 440, 440, 440, 440, 440, 441, 441, 441, 441, 441, 441, 441, 441, 441, + 441, 81, 81, 81, 436, 436, 436, 442, 442, 442, 442, 442, 442, 442, 442, + 442, 442, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + 443, 443, 444, 444, 444, 444, 444, 444, 445, 445, 93, 81, 81, 81, 81, 81, + 81, 81, 446, 446, 446, 446, 446, 446, 446, 446, 96, 96, 96, 326, 447, + 156, 156, 156, 156, 156, 96, 96, 156, 156, 156, 156, 96, 448, 447, 447, + 447, 447, 447, 447, 447, 449, 449, 449, 449, 156, 449, 449, 449, 449, + 448, 448, 96, 449, 449, 448, 96, 96, 81, 81, 81, 81, 81, 81, 56, 56, 56, + 56, 56, 56, 79, 79, 79, 79, 79, 93, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 82, 82, 82, 82, 82, 59, 59, 59, 59, 82, 82, 82, 82, 82, 56, 56, 56, 56, + 56, 450, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 82, 96, 96, 156, 96, 96, 96, 96, 96, 96, 96, 156, + 96, 96, 451, 452, 156, 453, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 454, 455, 455, 156, 81, 96, 456, + 156, 96, 156, 52, 56, 52, 56, 52, 56, 56, 56, 56, 56, 56, 56, 56, 56, 52, + 56, 79, 79, 79, 79, 79, 79, 79, 79, 78, 78, 78, 78, 78, 78, 78, 78, 79, + 79, 79, 79, 79, 79, 81, 81, 78, 78, 78, 78, 78, 78, 81, 81, 81, 78, 81, + 78, 81, 78, 81, 78, 457, 457, 457, 457, 457, 457, 457, 457, 79, 79, 79, + 79, 79, 81, 79, 79, 78, 78, 78, 78, 457, 80, 79, 80, 80, 80, 79, 79, 79, + 81, 79, 79, 78, 78, 78, 78, 457, 80, 80, 80, 79, 79, 79, 79, 81, 81, 79, + 79, 78, 78, 78, 78, 81, 80, 80, 80, 78, 78, 78, 78, 78, 80, 80, 80, 81, + 81, 79, 79, 79, 81, 79, 79, 78, 78, 78, 78, 457, 458, 80, 81, 459, 459, + 459, 459, 459, 459, 459, 460, 459, 459, 459, 461, 462, 463, 464, 465, + 466, 467, 468, 466, 469, 470, 38, 84, 471, 472, 473, 42, 471, 472, 473, + 42, 38, 38, 474, 84, 475, 475, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 33, 484, 485, 484, 484, 485, 486, 487, 487, 84, 42, 50, 38, 488, + 488, 474, 489, 489, 84, 84, 84, 490, 473, 491, 488, 488, 488, 84, 84, 84, + 84, 84, 84, 84, 84, 492, 84, 489, 84, 373, 84, 373, 373, 373, 373, 84, + 373, 373, 459, 493, 494, 494, 494, 494, 81, 495, 496, 497, 498, 499, 499, + 499, 499, 499, 499, 500, 59, 81, 81, 47, 500, 500, 500, 500, 500, 501, + 501, 492, 473, 491, 502, 500, 47, 47, 47, 47, 500, 500, 500, 500, 500, + 501, 501, 492, 473, 491, 81, 59, 59, 59, 59, 59, 81, 81, 81, 278, 278, + 278, 278, 278, 278, 278, 503, 278, 504, 278, 278, 36, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 503, 278, 278, 278, 278, 503, 278, 278, 503, + 278, 505, 505, 505, 505, 505, 505, 505, 505, 96, 96, 447, 447, 96, 96, + 96, 96, 447, 447, 447, 96, 96, 412, 412, 412, 412, 96, 412, 412, 412, + 447, 447, 96, 156, 96, 447, 447, 156, 156, 156, 156, 96, 81, 81, 81, 81, + 81, 81, 81, 40, 40, 506, 507, 40, 508, 40, 506, 40, 507, 49, 506, 506, + 506, 49, 49, 506, 506, 506, 509, 40, 506, 510, 40, 492, 506, 506, 506, + 506, 506, 40, 40, 40, 508, 508, 40, 506, 40, 85, 40, 506, 40, 52, 511, + 506, 506, 512, 49, 506, 506, 52, 506, 49, 449, 449, 449, 449, 49, 40, 40, + 49, 49, 506, 506, 492, 492, 492, 492, 492, 506, 49, 49, 49, 49, 40, 492, + 40, 40, 56, 313, 513, 513, 513, 514, 51, 515, 513, 513, 513, 513, 513, + 51, 514, 514, 51, 513, 516, 516, 516, 516, 516, 516, 516, 516, 516, 516, + 516, 516, 517, 517, 517, 517, 516, 516, 517, 517, 517, 517, 517, 517, + 517, 517, 517, 52, 56, 517, 517, 517, 517, 51, 40, 40, 81, 81, 81, 81, + 54, 54, 54, 54, 54, 508, 508, 508, 508, 508, 492, 492, 40, 40, 40, 40, + 492, 40, 40, 492, 40, 40, 492, 40, 40, 40, 40, 40, 40, 40, 492, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 44, 44, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 492, 492, 40, 40, 54, 40, 54, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 44, 40, 40, 40, 40, 492, 492, 492, 492, 492, 492, 492, 492, 492, + 492, 492, 492, 54, 492, 54, 54, 492, 492, 492, 54, 54, 492, 492, 54, 492, + 492, 492, 54, 492, 54, 518, 519, 492, 54, 492, 492, 492, 492, 54, 492, + 492, 54, 54, 54, 54, 492, 492, 54, 492, 54, 492, 54, 54, 54, 54, 54, 54, + 492, 54, 492, 492, 492, 492, 492, 54, 54, 54, 54, 492, 492, 492, 492, 54, + 54, 492, 492, 54, 492, 492, 492, 54, 492, 492, 492, 492, 492, 54, 492, + 492, 492, 492, 492, 54, 54, 492, 492, 54, 54, 54, 54, 492, 492, 54, 54, + 492, 492, 54, 54, 492, 492, 492, 492, 492, 54, 492, 492, 492, 54, 492, + 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 54, 492, 492, + 492, 492, 492, 492, 492, 520, 473, 491, 473, 491, 40, 40, 40, 40, 40, 40, + 508, 40, 40, 40, 40, 40, 40, 40, 521, 521, 40, 40, 40, 40, 492, 492, 40, + 40, 40, 40, 40, 40, 40, 522, 523, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 40, + 492, 40, 40, 40, 40, 40, 40, 40, 40, 313, 40, 40, 40, 40, 40, 492, 492, + 492, 492, 492, 492, 492, 492, 492, 40, 40, 40, 40, 40, 524, 524, 524, + 524, 40, 40, 40, 521, 525, 525, 521, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 81, 40, 40, 40, 81, 81, 81, 81, 81, 51, 51, 51, 51, 51, 51, 51, + 51, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 526, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 515, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 514, 508, 508, 508, 508, 508, 508, 508, + 508, 508, 508, 508, 508, 40, 40, 40, 40, 508, 508, 508, 508, 527, 40, 40, + 40, 40, 40, 508, 508, 508, 508, 40, 40, 508, 508, 40, 508, 508, 508, 508, + 508, 508, 508, 40, 40, 40, 40, 40, 40, 40, 40, 508, 508, 40, 40, 508, 54, + 40, 40, 40, 40, 508, 508, 40, 40, 508, 54, 40, 40, 40, 40, 508, 508, 508, + 40, 40, 508, 40, 40, 508, 508, 40, 40, 40, 40, 40, 40, 40, 508, 492, 492, + 492, 492, 492, 528, 528, 492, 525, 525, 525, 525, 40, 508, 508, 40, 40, + 508, 40, 40, 40, 40, 508, 508, 40, 40, 40, 40, 521, 521, 527, 527, 525, + 40, 525, 525, 529, 530, 529, 525, 40, 525, 525, 525, 40, 40, 40, 40, 508, + 40, 508, 40, 40, 40, 40, 40, 524, 524, 524, 524, 524, 524, 524, 524, 524, + 524, 524, 524, 40, 40, 40, 40, 508, 508, 40, 508, 508, 508, 40, 508, 529, + 508, 508, 40, 508, 508, 40, 54, 40, 40, 40, 40, 40, 40, 40, 521, 40, 40, + 40, 524, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 508, 508, 40, 524, 40, + 40, 40, 40, 40, 40, 40, 40, 524, 524, 313, 40, 40, 40, 40, 40, 40, 40, + 40, 521, 521, 529, 525, 525, 525, 525, 521, 521, 529, 529, 529, 508, 508, + 508, 508, 529, 524, 529, 529, 529, 508, 529, 521, 508, 508, 508, 529, + 529, 508, 508, 529, 508, 508, 529, 529, 529, 40, 508, 40, 40, 40, 40, + 508, 508, 521, 508, 508, 508, 508, 508, 508, 529, 521, 521, 529, 521, + 508, 529, 529, 531, 521, 508, 508, 521, 529, 529, 525, 525, 525, 525, + 525, 524, 40, 40, 525, 525, 532, 532, 530, 530, 40, 40, 524, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 44, 40, 40, 40, 40, 40, 40, 524, 40, + 524, 40, 40, 40, 40, 524, 524, 524, 40, 533, 40, 40, 40, 534, 534, 534, + 534, 534, 534, 40, 535, 535, 525, 40, 40, 40, 473, 491, 473, 491, 473, + 491, 473, 491, 473, 491, 473, 491, 473, 491, 51, 51, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 40, 524, 524, 524, 40, 40, 40, + 40, 40, 40, 40, 524, 492, 492, 492, 492, 492, 473, 491, 492, 492, 492, + 492, 492, 492, 492, 16, 31, 16, 31, 16, 31, 16, 31, 473, 491, 536, 536, + 536, 536, 536, 536, 536, 536, 492, 492, 492, 473, 491, 16, 31, 473, 491, + 473, 491, 473, 491, 473, 491, 473, 491, 492, 492, 492, 492, 492, 492, + 492, 473, 491, 473, 491, 492, 492, 492, 492, 492, 492, 492, 492, 473, + 491, 492, 492, 40, 40, 40, 524, 524, 40, 40, 40, 492, 492, 492, 492, 492, + 40, 40, 492, 492, 492, 492, 492, 492, 40, 40, 40, 524, 40, 40, 40, 40, + 533, 508, 508, 40, 40, 40, 40, 81, 81, 40, 40, 40, 40, 40, 40, 40, 40, + 81, 81, 40, 40, 81, 81, 81, 40, 40, 40, 40, 81, 40, 40, 40, 40, 40, 40, + 81, 81, 81, 81, 40, 40, 40, 40, 537, 537, 537, 537, 537, 537, 537, 537, + 537, 537, 537, 537, 537, 537, 537, 81, 538, 538, 538, 538, 538, 538, 538, + 538, 538, 538, 538, 538, 538, 538, 538, 81, 52, 56, 52, 52, 52, 56, 56, + 52, 56, 52, 56, 52, 56, 52, 52, 52, 52, 56, 52, 56, 56, 52, 56, 56, 56, + 56, 56, 56, 59, 59, 52, 52, 87, 88, 87, 88, 88, 539, 539, 539, 539, 539, + 539, 87, 88, 87, 88, 540, 540, 540, 87, 88, 81, 81, 81, 81, 81, 541, 542, + 542, 542, 543, 541, 542, 544, 544, 544, 544, 544, 544, 544, 544, 544, + 544, 544, 544, 544, 544, 81, 544, 81, 81, 81, 81, 81, 544, 81, 81, 545, + 545, 545, 545, 545, 545, 545, 545, 81, 81, 81, 81, 81, 81, 81, 546, 547, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 548, 95, 95, 95, + 95, 95, 95, 95, 95, 549, 549, 42, 50, 42, 50, 549, 549, 549, 42, 50, 549, + 42, 50, 373, 373, 373, 373, 373, 373, 373, 373, 84, 468, 550, 373, 551, + 84, 42, 50, 84, 84, 42, 50, 473, 491, 473, 491, 473, 491, 473, 491, 373, + 373, 373, 373, 371, 60, 373, 373, 84, 373, 373, 84, 84, 84, 84, 84, 552, + 552, 373, 373, 373, 84, 468, 373, 473, 373, 373, 373, 373, 373, 373, 373, + 81, 81, 81, 81, 81, 81, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, + 81, 553, 553, 553, 553, 553, 553, 553, 553, 553, 81, 81, 81, 81, 553, + 553, 553, 553, 553, 553, 81, 81, 521, 521, 521, 521, 521, 521, 521, 521, + 521, 521, 521, 521, 81, 81, 81, 81, 554, 555, 555, 556, 521, 557, 558, + 559, 522, 523, 522, 523, 522, 523, 522, 523, 522, 523, 521, 521, 522, + 523, 522, 523, 522, 523, 522, 523, 560, 522, 523, 523, 521, 559, 559, + 559, 559, 559, 559, 559, 559, 559, 561, 562, 563, 564, 565, 565, 566, + 567, 567, 567, 567, 568, 521, 521, 559, 559, 559, 557, 569, 556, 521, + 525, 81, 570, 571, 570, 571, 570, 571, 570, 571, 570, 571, 571, 571, 571, + 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 570, + 571, 571, 571, 571, 571, 571, 571, 570, 571, 570, 571, 570, 571, 571, + 571, 571, 571, 571, 570, 571, 571, 571, 571, 571, 571, 570, 570, 81, 81, + 572, 572, 573, 573, 574, 574, 571, 560, 575, 576, 575, 576, 575, 576, + 575, 576, 575, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, + 576, 576, 576, 576, 576, 576, 575, 576, 576, 576, 576, 576, 576, 576, + 575, 576, 575, 576, 575, 576, 576, 576, 576, 576, 576, 575, 576, 576, + 576, 576, 576, 576, 575, 575, 576, 576, 576, 576, 577, 578, 579, 579, + 576, 81, 81, 81, 81, 81, 580, 580, 580, 580, 580, 580, 580, 580, 580, + 580, 580, 580, 580, 580, 580, 580, 580, 580, 81, 81, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 81, 582, 582, 583, 583, 583, 583, 582, 582, 582, 582, + 582, 582, 582, 582, 582, 582, 580, 580, 580, 81, 81, 81, 81, 81, 575, + 575, 575, 575, 575, 575, 575, 575, 584, 584, 584, 584, 584, 584, 584, + 584, 584, 584, 584, 584, 584, 585, 585, 81, 583, 583, 583, 583, 583, 583, + 583, 583, 583, 583, 582, 582, 582, 582, 582, 582, 586, 586, 586, 586, + 586, 586, 586, 586, 521, 587, 587, 587, 587, 587, 587, 587, 587, 587, + 587, 587, 587, 587, 587, 587, 584, 584, 584, 584, 585, 585, 585, 582, + 582, 587, 587, 587, 587, 587, 587, 587, 582, 582, 582, 582, 521, 521, + 521, 521, 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, 588, + 588, 588, 588, 81, 582, 582, 582, 582, 582, 582, 582, 521, 521, 521, 521, + 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 521, 521, 589, + 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 590, + 590, 590, 590, 590, 590, 590, 590, 590, 590, 589, 589, 589, 590, 590, + 590, 590, 590, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, + 591, 591, 592, 591, 591, 591, 591, 591, 591, 591, 81, 81, 81, 593, 593, + 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 81, 594, + 594, 594, 594, 594, 594, 594, 594, 595, 595, 595, 595, 595, 595, 596, + 596, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 598, + 599, 600, 599, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 597, + 597, 81, 81, 81, 81, 90, 93, 90, 93, 90, 93, 602, 95, 97, 97, 97, 603, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 603, 604, 90, 93, 90, 93, 450, + 450, 95, 95, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, 607, 607, + 608, 609, 609, 609, 609, 609, 62, 62, 62, 62, 62, 62, 62, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 62, 62, 52, 56, 52, 56, 52, 56, 56, 56, 52, 56, 52, + 56, 52, 56, 59, 56, 56, 56, 56, 56, 56, 56, 56, 52, 56, 52, 56, 52, 52, + 56, 60, 610, 610, 52, 56, 52, 56, 57, 52, 56, 52, 56, 56, 56, 52, 56, 52, + 56, 52, 52, 52, 52, 52, 81, 52, 52, 52, 52, 52, 56, 52, 56, 81, 81, 81, + 81, 81, 81, 81, 57, 59, 59, 56, 57, 57, 57, 57, 57, 611, 611, 612, 611, + 611, 611, 613, 611, 611, 611, 611, 612, 611, 611, 611, 611, 611, 611, + 611, 611, 611, 611, 611, 611, 611, 611, 611, 614, 614, 612, 612, 614, + 615, 615, 615, 615, 81, 81, 81, 81, 616, 616, 616, 616, 616, 616, 313, + 313, 503, 512, 81, 81, 81, 81, 81, 81, 617, 617, 617, 617, 617, 617, 617, + 617, 617, 617, 617, 617, 618, 618, 619, 619, 620, 620, 621, 621, 621, + 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, 621, + 621, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 622, 623, 81, 81, 81, 81, 81, 81, 81, 81, 624, 624, 625, + 625, 625, 625, 625, 625, 625, 625, 625, 625, 81, 81, 81, 81, 81, 81, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 194, 194, 194, 194, 194, + 194, 200, 200, 200, 194, 626, 194, 81, 81, 627, 627, 627, 627, 627, 627, + 627, 627, 627, 627, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, + 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 629, 629, 629, 629, + 629, 630, 630, 630, 198, 631, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 633, 633, 633, 633, 633, 633, 633, + 633, 633, 633, 633, 634, 635, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 636, 328, 328, 328, 328, 328, 81, 81, 81, 637, 637, 637, 638, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 640, + 638, 638, 637, 637, 637, 637, 638, 638, 637, 638, 638, 638, 641, 642, + 642, 642, 642, 642, 642, 643, 643, 643, 642, 642, 642, 642, 81, 61, 644, + 644, 644, 644, 644, 644, 644, 644, 644, 644, 81, 81, 81, 81, 642, 642, + 314, 314, 314, 314, 314, 316, 645, 314, 319, 319, 314, 314, 314, 314, + 314, 81, 646, 646, 646, 646, 646, 646, 646, 646, 646, 647, 647, 647, 647, + 647, 647, 648, 648, 647, 647, 648, 648, 647, 647, 81, 646, 646, 646, 647, + 646, 646, 646, 646, 646, 646, 646, 646, 647, 648, 81, 81, 649, 649, 649, + 649, 649, 649, 649, 649, 649, 649, 81, 81, 650, 651, 651, 651, 645, 314, + 314, 314, 314, 314, 314, 323, 323, 323, 314, 315, 316, 315, 314, 314, + 652, 652, 652, 652, 652, 652, 652, 652, 653, 652, 653, 653, 654, 652, + 652, 653, 653, 652, 652, 652, 652, 652, 653, 653, 652, 653, 652, 81, 81, + 81, 81, 81, 81, 81, 81, 652, 652, 655, 656, 656, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 658, 659, 659, 658, 658, 660, 660, 657, + 661, 661, 658, 662, 81, 81, 331, 331, 331, 331, 331, 331, 81, 56, 56, 56, + 610, 59, 59, 59, 59, 56, 56, 56, 56, 56, 79, 81, 81, 338, 338, 338, 338, + 338, 338, 338, 338, 657, 657, 657, 658, 658, 659, 658, 658, 659, 658, + 658, 660, 658, 662, 81, 81, 663, 663, 663, 663, 663, 663, 663, 663, 663, + 663, 81, 81, 81, 81, 81, 81, 664, 665, 665, 665, 665, 665, 665, 665, 665, + 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 664, 665, 665, + 665, 665, 665, 665, 665, 81, 81, 81, 81, 329, 329, 329, 329, 329, 329, + 329, 81, 81, 81, 81, 330, 330, 330, 330, 330, 330, 330, 330, 330, 81, 81, + 81, 81, 666, 666, 666, 666, 666, 666, 666, 666, 667, 667, 667, 667, 667, + 667, 667, 667, 589, 589, 590, 590, 590, 590, 590, 590, 56, 56, 56, 56, + 56, 56, 56, 81, 81, 81, 81, 101, 101, 101, 101, 101, 81, 81, 81, 81, 81, + 129, 668, 129, 129, 669, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 81, 129, 129, 129, 129, 129, 81, 129, 81, 129, 129, + 81, 129, 129, 81, 129, 129, 146, 146, 670, 670, 670, 670, 670, 670, 670, + 670, 670, 670, 670, 670, 670, 670, 670, 670, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 491, 473, + 81, 81, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 135, 138, 81, + 81, 671, 671, 671, 671, 671, 671, 671, 671, 672, 555, 555, 672, 672, 673, + 673, 522, 523, 674, 81, 81, 81, 81, 81, 81, 96, 96, 96, 96, 96, 96, 96, + 156, 156, 156, 156, 156, 156, 156, 95, 95, 556, 566, 566, 675, 675, 522, + 523, 522, 523, 522, 523, 522, 523, 522, 523, 522, 523, 522, 523, 522, + 523, 556, 556, 522, 523, 556, 556, 556, 556, 675, 675, 675, 676, 556, + 676, 81, 577, 677, 673, 673, 566, 522, 523, 522, 523, 522, 523, 678, 556, + 556, 679, 680, 681, 681, 681, 81, 556, 682, 683, 556, 81, 81, 81, 81, + 146, 146, 146, 146, 146, 81, 81, 493, 81, 684, 685, 686, 687, 688, 685, + 685, 689, 690, 685, 691, 692, 693, 692, 694, 695, 695, 695, 695, 695, + 695, 695, 695, 695, 695, 696, 697, 698, 698, 698, 684, 685, 699, 699, + 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 699, 699, 689, 685, 690, 700, 701, 700, 702, 702, 702, 702, 702, 702, + 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 689, 698, + 690, 698, 689, 690, 703, 704, 705, 703, 706, 707, 708, 708, 708, 708, + 708, 708, 708, 708, 708, 709, 707, 707, 707, 707, 707, 707, 707, 707, + 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 710, + 710, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, + 711, 711, 81, 81, 81, 711, 711, 711, 711, 711, 711, 81, 81, 711, 711, + 711, 81, 81, 81, 712, 687, 698, 700, 713, 687, 687, 81, 714, 715, 715, + 715, 715, 714, 714, 81, 81, 716, 716, 716, 717, 508, 81, 81, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 81, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 81, 718, 718, 718, 81, 718, 718, 81, 718, + 718, 718, 718, 718, 718, 718, 81, 81, 718, 718, 718, 81, 81, 81, 81, 81, + 198, 373, 198, 81, 81, 81, 81, 616, 616, 616, 616, 616, 616, 616, 616, + 616, 616, 616, 616, 616, 81, 81, 81, 313, 719, 719, 719, 719, 719, 719, + 719, 719, 719, 719, 719, 719, 719, 720, 720, 720, 720, 721, 721, 721, + 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, + 720, 720, 721, 722, 722, 81, 40, 40, 40, 40, 81, 81, 81, 81, 721, 81, 81, + 81, 81, 81, 81, 81, 313, 313, 313, 313, 313, 156, 81, 81, 723, 723, 723, + 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 81, 81, 81, 724, 724, + 724, 724, 724, 724, 724, 724, 724, 81, 81, 81, 81, 81, 81, 81, 156, 500, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, + 500, 500, 500, 500, 81, 81, 81, 81, 725, 725, 725, 725, 725, 725, 725, + 725, 726, 726, 726, 726, 81, 81, 81, 81, 81, 81, 81, 81, 81, 725, 725, + 725, 727, 727, 727, 727, 727, 727, 727, 727, 727, 728, 727, 727, 727, + 727, 727, 727, 727, 727, 728, 81, 81, 81, 81, 81, 729, 729, 729, 729, + 729, 729, 729, 729, 729, 729, 729, 729, 729, 729, 730, 730, 730, 730, + 730, 81, 81, 81, 81, 81, 731, 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 81, 732, 733, 733, 733, 733, 733, 733, 733, 733, + 733, 733, 733, 733, 81, 81, 81, 81, 734, 735, 735, 735, 735, 735, 81, 81, + 736, 736, 736, 736, 736, 736, 736, 736, 737, 737, 737, 737, 737, 737, + 737, 737, 738, 738, 738, 738, 738, 738, 738, 738, 739, 739, 739, 739, + 739, 739, 739, 739, 739, 739, 739, 739, 739, 739, 81, 81, 740, 740, 740, + 740, 740, 740, 740, 740, 740, 740, 81, 81, 81, 81, 81, 81, 741, 741, 741, + 741, 741, 741, 741, 741, 741, 741, 741, 741, 81, 81, 81, 81, 742, 742, + 742, 742, 742, 742, 742, 742, 742, 742, 742, 742, 81, 81, 81, 81, 743, + 743, 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 744, + 744, 744, 744, 744, 744, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 745, + 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, + 746, 81, 746, 746, 746, 746, 746, 746, 81, 81, 747, 747, 747, 747, 747, + 747, 81, 81, 747, 81, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, + 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 81, 747, 747, 81, 81, + 81, 747, 81, 81, 747, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, + 748, 748, 748, 748, 81, 749, 750, 750, 750, 750, 750, 750, 750, 750, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, 751, + 752, 752, 753, 753, 753, 753, 753, 753, 753, 754, 754, 754, 754, 754, + 754, 754, 754, 754, 754, 754, 754, 754, 754, 754, 81, 81, 81, 81, 81, 81, + 81, 81, 755, 755, 755, 755, 755, 755, 755, 755, 755, 756, 756, 756, 756, + 756, 756, 756, 756, 756, 756, 756, 81, 756, 756, 81, 81, 81, 81, 81, 757, + 757, 757, 757, 757, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, + 758, 758, 758, 758, 759, 759, 759, 759, 759, 759, 81, 81, 81, 760, 761, + 761, 761, 761, 761, 761, 761, 761, 761, 761, 81, 81, 81, 81, 81, 762, + 763, 763, 763, 763, 763, 763, 763, 763, 764, 764, 764, 764, 764, 764, + 764, 764, 81, 81, 81, 81, 765, 765, 764, 764, 765, 765, 765, 765, 765, + 765, 765, 765, 81, 81, 765, 765, 765, 765, 765, 765, 766, 767, 767, 767, + 81, 767, 767, 81, 81, 81, 81, 81, 767, 768, 767, 769, 766, 766, 766, 766, + 81, 766, 766, 766, 81, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, + 766, 766, 766, 766, 766, 766, 766, 766, 766, 81, 81, 81, 81, 769, 770, + 768, 81, 81, 81, 81, 771, 772, 772, 772, 772, 772, 772, 772, 772, 773, + 773, 773, 773, 773, 773, 773, 773, 774, 81, 81, 81, 81, 81, 81, 81, 775, + 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 776, 776, + 777, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, + 779, 779, 779, 780, 780, 780, 780, 780, 780, 780, 780, 781, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 782, 783, 81, 81, 81, + 81, 784, 784, 784, 784, 784, 785, 785, 785, 785, 785, 785, 786, 81, 787, + 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 81, 81, + 81, 788, 788, 788, 788, 788, 788, 788, 789, 789, 789, 789, 789, 789, 789, + 789, 789, 789, 789, 789, 789, 789, 81, 81, 790, 790, 790, 790, 790, 790, + 790, 790, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 81, 81, + 81, 81, 81, 792, 792, 792, 792, 792, 792, 792, 792, 793, 793, 793, 793, + 793, 793, 793, 793, 793, 793, 81, 81, 81, 81, 81, 81, 81, 794, 794, 794, + 794, 81, 81, 81, 81, 795, 795, 795, 795, 795, 795, 795, 796, 796, 796, + 796, 796, 796, 796, 796, 796, 81, 81, 81, 81, 81, 81, 81, 797, 797, 797, + 797, 797, 797, 797, 797, 797, 797, 797, 81, 81, 81, 81, 81, 798, 798, + 798, 798, 798, 798, 798, 798, 798, 798, 798, 81, 81, 81, 81, 81, 81, 81, + 799, 799, 799, 799, 799, 799, 800, 800, 800, 800, 800, 800, 800, 800, + 800, 800, 800, 800, 800, 800, 800, 81, 801, 802, 801, 803, 803, 803, 803, + 803, 803, 803, 803, 803, 803, 803, 803, 803, 802, 802, 802, 802, 802, + 802, 802, 802, 802, 802, 802, 802, 802, 802, 804, 805, 805, 806, 806, + 806, 806, 806, 81, 81, 81, 81, 807, 807, 807, 807, 807, 807, 807, 807, + 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 808, 808, + 808, 808, 808, 808, 808, 808, 808, 808, 81, 81, 81, 81, 81, 81, 81, 804, + 809, 809, 810, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, + 811, 811, 810, 810, 810, 809, 809, 809, 809, 810, 810, 812, 813, 814, + 814, 815, 816, 816, 816, 816, 81, 81, 81, 81, 81, 81, 817, 817, 817, 817, + 817, 817, 817, 817, 817, 81, 81, 81, 81, 81, 81, 81, 818, 818, 818, 818, + 818, 818, 818, 818, 818, 818, 81, 81, 81, 81, 81, 81, 819, 819, 819, 820, + 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, 820, + 820, 820, 820, 820, 820, 821, 821, 821, 821, 821, 822, 821, 821, 821, + 821, 821, 821, 823, 823, 81, 824, 824, 824, 824, 824, 824, 824, 824, 824, + 824, 825, 825, 825, 825, 81, 81, 81, 81, 826, 826, 826, 826, 826, 826, + 826, 826, 826, 826, 826, 827, 828, 829, 826, 81, 830, 830, 831, 832, 832, + 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, + 831, 831, 831, 830, 830, 830, 830, 830, 830, 830, 830, 830, 831, 833, + 832, 832, 832, 832, 834, 834, 835, 834, 835, 836, 830, 830, 835, 81, 81, + 837, 837, 837, 837, 837, 837, 837, 837, 837, 837, 832, 838, 832, 834, + 834, 834, 81, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 839, 81, 81, 81, 840, 840, 840, 840, + 840, 840, 840, 840, 840, 840, 81, 840, 840, 840, 840, 840, 840, 840, 840, + 840, 841, 841, 841, 842, 842, 842, 841, 841, 842, 843, 844, 842, 845, + 845, 846, 845, 845, 846, 842, 81, 847, 847, 847, 847, 847, 847, 847, 81, + 847, 81, 847, 847, 847, 847, 81, 847, 847, 847, 847, 847, 847, 847, 847, + 847, 847, 847, 847, 847, 847, 847, 81, 847, 847, 848, 81, 81, 81, 81, 81, + 81, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, 849, + 849, 850, 851, 851, 851, 850, 850, 850, 850, 850, 850, 852, 853, 81, 81, + 81, 81, 81, 854, 854, 854, 854, 854, 854, 854, 854, 854, 854, 81, 81, 81, + 81, 81, 81, 855, 855, 856, 856, 81, 857, 857, 857, 857, 857, 857, 857, + 857, 81, 81, 857, 857, 81, 81, 857, 857, 857, 857, 857, 857, 857, 857, + 857, 857, 857, 857, 857, 857, 81, 857, 857, 857, 857, 857, 857, 857, 81, + 857, 857, 81, 857, 857, 857, 857, 857, 81, 81, 858, 857, 856, 856, 855, + 856, 856, 856, 856, 81, 81, 856, 856, 81, 81, 856, 856, 859, 81, 81, 857, + 81, 81, 81, 81, 81, 81, 856, 81, 81, 81, 81, 81, 857, 857, 857, 857, 857, + 856, 856, 81, 81, 860, 860, 860, 860, 860, 860, 860, 81, 81, 81, 861, + 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 861, 862, 862, + 862, 863, 863, 863, 863, 863, 863, 863, 863, 862, 862, 864, 863, 863, + 862, 865, 861, 861, 861, 861, 866, 866, 866, 866, 867, 868, 868, 868, + 868, 868, 868, 868, 868, 868, 868, 81, 866, 81, 867, 81, 81, 869, 869, + 869, 869, 869, 869, 869, 869, 870, 870, 870, 871, 871, 871, 871, 871, + 871, 870, 871, 870, 870, 870, 870, 871, 871, 870, 872, 873, 869, 869, + 874, 869, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 81, 81, 81, + 81, 81, 81, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, + 876, 876, 876, 877, 877, 877, 878, 878, 878, 878, 81, 81, 877, 877, 877, + 877, 878, 878, 877, 879, 880, 881, 882, 882, 883, 883, 884, 884, 884, + 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, + 882, 876, 876, 876, 876, 878, 878, 81, 81, 885, 885, 885, 885, 885, 885, + 885, 885, 886, 886, 886, 887, 887, 887, 887, 887, 887, 887, 887, 886, + 886, 887, 886, 888, 887, 889, 889, 890, 885, 81, 81, 81, 891, 891, 891, + 891, 891, 891, 891, 891, 891, 891, 81, 81, 81, 81, 81, 81, 892, 892, 892, + 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 81, 81, 81, 893, 893, + 893, 893, 893, 893, 893, 893, 893, 893, 893, 894, 895, 894, 895, 895, + 894, 894, 894, 894, 894, 894, 896, 897, 898, 898, 898, 898, 898, 898, + 898, 898, 898, 898, 81, 81, 81, 81, 81, 81, 899, 899, 899, 899, 899, 899, + 899, 899, 899, 899, 81, 81, 81, 900, 900, 900, 901, 901, 900, 900, 900, + 900, 901, 900, 900, 900, 900, 902, 81, 81, 81, 81, 903, 903, 903, 903, + 903, 903, 903, 903, 903, 903, 904, 904, 905, 905, 905, 906, 907, 907, + 907, 907, 907, 907, 907, 907, 908, 908, 908, 908, 908, 908, 908, 908, + 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 910, 910, 910, 910, + 910, 910, 910, 910, 910, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 911, 912, 913, 913, 913, 913, 913, 913, 914, 914, 913, 913, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, + 913, 915, 913, 913, 913, 913, 914, 912, 913, 913, 913, 913, 916, 917, + 918, 918, 918, 918, 916, 917, 915, 919, 920, 920, 920, 920, 920, 920, + 921, 921, 920, 920, 920, 919, 919, 919, 919, 919, 919, 919, 919, 919, + 919, 919, 919, 919, 919, 919, 919, 81, 81, 919, 919, 919, 919, 920, 920, + 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 921, 920, 922, + 923, 923, 923, 81, 924, 924, 924, 923, 923, 81, 81, 81, 81, 81, 925, 925, + 925, 925, 925, 925, 925, 925, 925, 81, 81, 81, 81, 81, 81, 81, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 81, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 927, 928, 928, 928, 928, 928, 928, 928, 81, + 928, 928, 928, 928, 928, 928, 927, 929, 926, 930, 930, 930, 930, 930, 81, + 81, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 932, 932, 932, 932, + 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, + 932, 81, 81, 81, 933, 934, 935, 935, 935, 935, 935, 935, 935, 935, 935, + 935, 935, 935, 935, 935, 81, 81, 936, 936, 936, 936, 936, 936, 936, 936, + 936, 936, 936, 936, 936, 936, 81, 937, 936, 936, 936, 936, 936, 936, 936, + 937, 936, 936, 937, 936, 936, 81, 938, 938, 938, 938, 938, 938, 938, 81, + 938, 938, 81, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, + 938, 938, 939, 939, 939, 939, 939, 939, 81, 81, 81, 939, 81, 939, 939, + 81, 939, 939, 939, 940, 939, 941, 941, 938, 939, 942, 942, 942, 942, 942, + 942, 942, 942, 942, 942, 81, 81, 81, 81, 81, 81, 943, 943, 943, 943, 943, + 943, 943, 943, 943, 943, 81, 81, 81, 81, 81, 81, 944, 944, 944, 944, 944, + 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 81, 945, 945, 945, 945, + 945, 81, 81, 81, 943, 943, 943, 943, 81, 81, 81, 81, 946, 946, 946, 946, + 946, 946, 946, 946, 947, 947, 947, 948, 948, 948, 946, 946, 946, 946, + 948, 946, 946, 946, 947, 948, 947, 948, 946, 946, 946, 946, 946, 946, + 946, 947, 948, 948, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, + 946, 81, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, + 949, 950, 951, 949, 949, 949, 949, 949, 949, 949, 81, 605, 81, 81, 81, + 81, 81, 81, 81, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, + 952, 952, 952, 952, 81, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, + 81, 81, 81, 81, 954, 954, 955, 955, 955, 955, 955, 955, 955, 955, 955, + 955, 955, 955, 955, 955, 81, 81, 956, 956, 956, 956, 956, 957, 81, 81, + 958, 958, 958, 958, 958, 958, 958, 958, 959, 959, 959, 959, 959, 959, + 959, 960, 960, 960, 961, 961, 962, 962, 962, 962, 963, 963, 963, 963, + 960, 962, 81, 81, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 81, + 965, 965, 965, 965, 965, 965, 965, 81, 958, 958, 958, 958, 958, 81, 81, + 81, 81, 81, 958, 958, 958, 966, 966, 966, 966, 966, 966, 966, 966, 966, + 966, 966, 966, 966, 81, 81, 81, 966, 967, 967, 967, 967, 967, 967, 967, + 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, + 967, 81, 81, 81, 81, 81, 81, 81, 81, 968, 968, 968, 968, 969, 969, 969, + 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 970, 971, 81, 81, 81, + 81, 81, 81, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, + 972, 81, 81, 81, 972, 972, 972, 81, 81, 81, 81, 81, 576, 571, 571, 571, + 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 81, 973, 973, 973, + 973, 973, 973, 973, 973, 973, 973, 973, 973, 81, 81, 81, 81, 974, 974, + 974, 974, 974, 974, 974, 974, 974, 974, 974, 81, 81, 81, 81, 81, 974, + 974, 974, 974, 974, 81, 81, 81, 974, 81, 81, 81, 81, 81, 81, 81, 974, + 974, 81, 81, 975, 976, 977, 978, 499, 499, 499, 499, 81, 81, 81, 81, 313, + 313, 313, 313, 313, 313, 81, 81, 313, 313, 313, 313, 313, 313, 313, 81, + 81, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 313, 979, 979, + 447, 447, 447, 313, 313, 313, 980, 979, 979, 979, 979, 979, 499, 499, + 499, 499, 499, 499, 499, 499, 156, 156, 156, 156, 156, 156, 156, 156, + 313, 313, 96, 96, 96, 96, 96, 156, 156, 313, 313, 313, 313, 313, 313, 96, + 96, 96, 96, 313, 313, 313, 81, 81, 81, 81, 81, 81, 81, 721, 721, 981, + 981, 981, 721, 81, 81, 616, 616, 81, 81, 81, 81, 81, 81, 506, 506, 506, + 506, 506, 506, 506, 506, 506, 506, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 506, 506, 506, 506, 506, 506, 506, + 506, 506, 506, 49, 49, 49, 49, 49, 49, 49, 81, 49, 49, 49, 49, 49, 49, + 506, 81, 506, 506, 81, 81, 506, 81, 81, 506, 506, 81, 81, 506, 506, 506, + 506, 81, 506, 506, 49, 49, 81, 49, 81, 49, 49, 49, 49, 49, 49, 49, 81, + 49, 49, 49, 49, 49, 49, 49, 506, 506, 81, 506, 506, 506, 506, 81, 81, + 506, 506, 506, 506, 506, 506, 506, 506, 81, 506, 506, 506, 506, 506, 506, + 506, 81, 49, 49, 506, 506, 81, 506, 506, 506, 506, 81, 506, 506, 506, + 506, 506, 81, 506, 81, 81, 81, 506, 506, 506, 506, 506, 506, 506, 81, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 81, 81, 506, 982, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 492, 49, 49, 49, 49, 49, 49, 506, 506, 506, 506, + 506, 506, 506, 506, 506, 982, 49, 49, 49, 49, 49, 49, 49, 49, 49, 492, + 49, 49, 506, 506, 506, 506, 506, 982, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 492, 49, 49, 49, 49, 49, 49, 506, 506, 506, 506, 506, 506, 506, 506, 506, + 982, 49, 492, 49, 49, 49, 49, 49, 49, 49, 49, 506, 49, 81, 81, 983, 983, + 983, 983, 983, 983, 983, 983, 983, 983, 984, 984, 984, 984, 984, 984, + 984, 984, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, + 985, 985, 985, 984, 984, 984, 984, 985, 985, 985, 985, 985, 985, 985, + 985, 985, 985, 984, 984, 984, 984, 984, 984, 984, 984, 985, 984, 984, + 984, 984, 984, 984, 985, 984, 984, 986, 986, 986, 986, 987, 81, 81, 81, + 81, 81, 81, 81, 985, 985, 985, 985, 985, 81, 985, 985, 985, 985, 985, + 985, 985, 988, 988, 988, 988, 988, 988, 988, 81, 988, 988, 988, 988, 988, + 988, 988, 988, 988, 81, 81, 988, 988, 988, 988, 988, 988, 988, 81, 988, + 988, 81, 988, 988, 988, 988, 988, 81, 81, 81, 81, 81, 989, 989, 989, 989, + 989, 989, 989, 989, 989, 989, 989, 989, 989, 81, 81, 990, 990, 990, 990, + 990, 990, 990, 990, 990, 991, 991, 991, 991, 991, 991, 991, 81, 992, 992, + 992, 992, 992, 992, 992, 992, 992, 992, 993, 993, 993, 993, 993, 993, + 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 994, 994, + 994, 994, 994, 994, 995, 81, 81, 81, 81, 81, 996, 996, 996, 996, 996, + 996, 996, 996, 996, 996, 81, 81, 81, 81, 997, 997, 146, 146, 146, 146, + 81, 146, 146, 146, 81, 146, 146, 81, 146, 81, 81, 146, 81, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 81, 146, 146, 146, 146, 81, 146, 81, + 146, 81, 81, 81, 81, 81, 81, 146, 81, 81, 81, 81, 146, 81, 146, 81, 146, + 81, 146, 146, 146, 81, 146, 81, 146, 81, 146, 81, 146, 81, 146, 146, 146, + 146, 81, 146, 81, 146, 146, 81, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 81, 81, 81, 81, 81, 146, 146, 146, 81, 146, 146, 146, 132, 132, 81, + 81, 81, 81, 81, 81, 525, 525, 525, 525, 521, 525, 525, 525, 525, 525, + 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 998, 998, 998, 998, + 998, 998, 998, 998, 998, 998, 998, 998, 525, 525, 525, 525, 525, 525, + 525, 998, 998, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, + 525, 525, 525, 521, 525, 525, 525, 525, 525, 525, 998, 998, 47, 47, 47, + 515, 515, 998, 998, 998, 526, 526, 526, 526, 526, 526, 313, 998, 526, + 526, 40, 40, 998, 998, 998, 998, 526, 526, 526, 526, 526, 526, 999, 526, + 526, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 526, 526, 526, + 526, 526, 526, 526, 526, 526, 526, 998, 998, 998, 998, 998, 998, 998, + 998, 998, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1001, 582, 582, 998, 998, 998, 998, 998, 582, 582, 582, 582, 998, 998, + 998, 998, 582, 998, 998, 998, 998, 998, 998, 998, 582, 582, 998, 998, + 998, 998, 998, 998, 521, 521, 521, 521, 521, 521, 998, 998, 521, 525, + 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 521, 521, 521, + 521, 521, 521, 521, 521, 521, 525, 521, 521, 521, 521, 521, 521, 525, + 521, 521, 521, 521, 521, 521, 521, 532, 521, 521, 521, 521, 521, 521, + 525, 525, 525, 525, 525, 525, 525, 525, 40, 40, 525, 525, 521, 521, 521, + 521, 521, 524, 524, 521, 521, 521, 521, 521, 524, 521, 521, 521, 521, + 521, 532, 532, 532, 521, 521, 532, 521, 521, 532, 530, 530, 525, 525, + 521, 521, 525, 525, 525, 521, 525, 525, 525, 521, 521, 521, 1002, 1002, + 1002, 1002, 1002, 521, 521, 521, 521, 521, 521, 521, 525, 521, 525, 532, + 532, 521, 521, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, + 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 532, + 532, 532, 532, 521, 521, 521, 521, 532, 521, 532, 521, 521, 521, 532, + 521, 521, 521, 521, 532, 532, 532, 521, 532, 532, 532, 524, 521, 524, + 521, 524, 521, 521, 521, 521, 521, 532, 521, 521, 521, 521, 524, 521, + 524, 524, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, 525, 525, + 521, 524, 524, 524, 524, 524, 524, 524, 521, 521, 521, 521, 521, 521, + 521, 521, 524, 524, 524, 524, 524, 524, 521, 521, 521, 521, 521, 524, + 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, 40, 40, 40, 40, + 525, 521, 521, 521, 521, 525, 525, 525, 525, 525, 530, 530, 525, 525, + 525, 525, 532, 525, 525, 525, 525, 525, 530, 525, 525, 525, 525, 532, + 532, 525, 525, 525, 525, 525, 40, 40, 40, 40, 40, 40, 40, 40, 525, 525, + 525, 525, 40, 40, 525, 521, 521, 521, 521, 521, 521, 521, 521, 521, 521, + 532, 532, 532, 521, 521, 521, 532, 532, 532, 532, 532, 40, 40, 40, 40, + 40, 40, 534, 534, 534, 1003, 1003, 1003, 40, 40, 40, 40, 521, 521, 521, + 532, 521, 521, 521, 521, 521, 521, 521, 521, 532, 532, 532, 521, 532, + 521, 521, 521, 521, 521, 525, 525, 525, 525, 525, 525, 532, 525, 525, + 525, 521, 521, 521, 525, 525, 998, 998, 998, 525, 525, 525, 521, 521, + 998, 998, 998, 525, 525, 525, 525, 521, 521, 521, 521, 521, 998, 998, + 998, 998, 998, 998, 998, 40, 40, 40, 40, 998, 998, 998, 998, 40, 40, 40, + 40, 40, 998, 998, 998, 40, 40, 998, 998, 998, 998, 998, 998, 40, 40, 40, + 40, 40, 40, 998, 998, 532, 532, 532, 532, 532, 521, 532, 532, 521, 521, + 521, 521, 521, 521, 532, 521, 532, 532, 521, 521, 521, 532, 532, 998, + 521, 521, 521, 521, 521, 998, 998, 998, 521, 521, 521, 521, 998, 998, + 998, 998, 521, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 521, 521, 521, 521, 521, 521, 521, 521, 521, 998, 998, 998, + 998, 998, 998, 998, 81, 81, 589, 589, 589, 589, 589, 589, 589, 590, 589, + 589, 589, 589, 589, 590, 590, 590, 589, 590, 590, 590, 590, 590, 590, + 590, 590, 590, 590, 590, 590, 590, 81, 81, 81, 499, 81, 81, 81, 81, 81, + 81, 499, 499, 499, 499, 499, 499, 499, 499, 667, 667, 667, 667, 667, 667, + 81, 81, }; /* decomposition data */ From 71c0a1429db7c7e7e32507be248c9457e1cbfc7d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 2 Oct 2017 18:56:10 +0200 Subject: [PATCH 0409/1326] [indic] Fix shaping of U+0A51 Mark it as matra below to allow the sequence U+0A15, U+0A51, U+0A47. Oh well... Fixes https://github.com/behdad/harfbuzz/issues/524 --- src/hb-ot-shape-complex-indic.cc | 6 ++++++ .../85fe0be440c64ac77699e21c2f1bd933a919167e.ttf | Bin 0 -> 1224 bytes test/shaping/tests/indic-syllable.tests | 1 + 3 files changed, 7 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/85fe0be440c64ac77699e21c2f1bd933a919167e.ttf diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index c8640cc56..d16816016 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -208,6 +208,12 @@ set_indic_properties (hb_glyph_info_t &info) cat = OT_M; pos = POS_ABOVE_C; } + else if (unlikely (u == 0x0A51u)) + { + /* https://github.com/behdad/harfbuzz/issues/524 */ + cat = OT_M; + pos = POS_BELOW_C; + } /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, * so the Indic shaper needs to know their categories. */ diff --git a/test/shaping/fonts/sha1sum/85fe0be440c64ac77699e21c2f1bd933a919167e.ttf b/test/shaping/fonts/sha1sum/85fe0be440c64ac77699e21c2f1bd933a919167e.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6198614b43d9845feb4884dfb90c01a17647bcf5 GIT binary patch literal 1224 zcmZ8gZ)jUp6#w1(Zu0W4>CDn}lqyNvrD8j#$(q5OxR&W-qIR=%ADpZ6u?mq6l=XdTo zzjMw#_dx&%;}i@Wv-UssINn1)V0=yO9_!%X&|>If4{?R~V{2%5;9BD6RX}}293LFo znVS8)v=xx2h>v9*dopk&dX9LFc<-1!JqeQ^jPt~yvBJsxmJiM(Dc|6%jOXl8U*^i+ zw2u;J#;IuTGq)2zN8B~;l*+z|+piHnNgOT|vo@A7O6(&JICgmw_lhlmSSOAjx1F5& zr)ekSwG$tlEKZmHdb8(Q;sUV+qxvV{@u{1LqZd1XL^9d!^>%h7`*vm0saR{KZ&!Ds zFVWH&i?u|}Sfo`Xlbs#jmS`-U$_QiK|3G5+_qi{wuAO`1$HQ&W%7~|R)!Q_@=c%Z> z^u&e2^z6$MS|4;K-cl|Tjlgk%J?P9@r7_xF% zU9TQ6dl5ntYhb9(4zrtyVC!!8>_bZn+e1EoB=Lu6e^jXJKU@`Or2CuuOEaW9e|r|J z1px#BGZssyQ@hO$7~S8bmges<{gE|yeLy_2dPTf1d?NHB>1nO-4tyvxo3!AvdimCJjcK}0-iw*V?+g7Of@Q~ z=8>%MDQQIzQt@e_-2Ik(VY+H>=Y}RT}AK;9l zjrrH>m&CeHJBXV&`EI!C7nH<4ND`+IuF;2iPaI^|_5#u#dC5U|q;SF^W8F)yJb@RP znzdj)g70d8Yor!apK5+DMD+l>A!sL58zs%&u#ZsM#=C4}uJ=u^%@;&3L;v0NT-(Y0 J|6F;b$A2+S Date: Mon, 2 Oct 2017 20:02:45 +0200 Subject: [PATCH 0410/1326] Tweak ligature component matching for ligature formation If two marks want to ligate and they belong to different components of the same ligature glyph, and said ligature glyph is to be ignored according to mark-filtering rules, then allow. Example Burmese senquence: U+1004,U+103A,U+1039,U+101B,U+103D,U+102D Test font provided by Norbert Lindenberg. Fixes https://github.com/behdad/harfbuzz/issues/545 --- src/hb-ot-layout-gsubgpos-private.hh | 59 +++++++++++++++--- ...c76d1bafde4a0b1026ebcc932d2e5c6fd02442.ttf | Bin 0 -> 1384 bytes test/shaping/tests/ligature-id.tests | 1 + 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/a6c76d1bafde4a0b1026ebcc932d2e5c6fd02442.ttf diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index 472628a39..f2ad9f1c9 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -374,6 +374,13 @@ struct hb_apply_context_t : inline void reject (void) { num_items++; match_glyph_data--; } + inline matcher_t::may_skip_t + may_skip (const hb_apply_context_t *c, + const hb_glyph_info_t &info) const + { + return matcher.may_skip (c, info); + } + inline bool next (void) { assert (num_items > 0); @@ -736,11 +743,17 @@ static inline bool match_input (hb_apply_context_t *c, * - Ligatures cannot be formed across glyphs attached to different components * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. - * However, it would be wrong to ligate that SHADDA,FATHA sequence.o - * There is an exception to this: If a ligature tries ligating with marks that - * belong to it itself, go ahead, assuming that the font designer knows what - * they are doing (otherwise it can break Indic stuff when a matra wants to - * ligate with a conjunct...) + * However, it would be wrong to ligate that SHADDA,FATHA sequence. + * There are a couple of exceptions to this: + * + * o If a ligature tries ligating with marks that belong to it itself, go ahead, + * assuming that the font designer knows what they are doing (otherwise it can + * break Indic stuff when a matra wants to ligate with a conjunct, + * + * o If two marks want to ligate and they belong to different components of the + * same ligature glyph, and said ligature glyph is to be ignored according to + * mark-filtering rules, then allow. + * https://github.com/behdad/harfbuzz/issues/545 */ bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); @@ -761,13 +774,41 @@ static inline bool match_input (hb_apply_context_t *c, unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]); - if (first_lig_id && first_lig_comp) { + if (first_lig_id && first_lig_comp) + { /* If first component was attached to a previous ligature component, * all subsequent components should be attached to the same ligature - * component, otherwise we shouldn't ligate them. */ + * component, otherwise we shouldn't ligate them... */ if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) - return_trace (false); - } else { + { + if (first_lig_id != this_lig_id && this_lig_id != 0) + return_trace (false); + + /* ...unless, we are attached to a base ligature and that base + * ligature is ignorable. */ + bool found = false; + const hb_glyph_info_t *out = buffer->out_info; + unsigned int j = buffer->out_len; + while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) + { + if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0) + { + j--; + found = true; + break; + } + j--; + } + + if (!found) + return_trace (false); + + if (skippy_iter.may_skip (c, out[j]) != hb_apply_context_t::matcher_t::SKIP_YES) + return_trace (false); + } + } + else + { /* If first component was NOT attached to a previous ligature component, * all subsequent components should also NOT be attached to any ligature * component, unless they are attached to the first component itself! */ diff --git a/test/shaping/fonts/sha1sum/a6c76d1bafde4a0b1026ebcc932d2e5c6fd02442.ttf b/test/shaping/fonts/sha1sum/a6c76d1bafde4a0b1026ebcc932d2e5c6fd02442.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7930a96b0bfa9a4024c56888a70032fceaeb76fb GIT binary patch literal 1384 zcmZuwOH30{6g}_Fz?6zu6!9BUtgoRjMAWJAb$8nqEW2;kt#t^bmf|r8ygc{ zm_`@6av?ibEKC>Z3Zn}*#)Y`CF_FYz=y>j%rW*B4-sjwRKWFZ{7Ye{y+=YeHZLLR- zVHmprYmw4}ZKqFl-T(CH8DNKqpSN}OBzilWwh+$=KGn6?oyM(EK(`WK>Q5yn!qd@j z#7~I3hsSRZ^=+Sj&hrP(mm`D8f%4jiZGg%W?;oL{q}t0+KTN!HBz0rD^lAPzF(GQk zuk|PK6|boOg19=BoSwi|oF~3V9KM=N4O&0fJfQv$;>5(Y>o?xVS`LtZGjSRUuGgsU zsqZKQc10TEmGR2j%DAe}uDJQk%1U(mvm}u6Y@jwIqgbzvwGwU+#IF&v=b` z#tIWVeu`=G9T#*j_j$N7$!JXUy)kObi9W3*VXAxcnS8mPDRK}s86~jvVZKNS0(wS# zq21rrMf$AwRb>5l^t7Kni6bF9bjS)bMwXnVGUQ*#jClvbk{`oX_Nqcos+hwg#N`M` zKIvgwXiw;1=n&r$1=J)cx0?H$dzV|tE&Rhe1Y})V_jzx<$(us;WsVMNN;aNVZC7XR9yR=t1=X#zMWr|Xp zH4!kjQh!mjvZ;@CbfY45JLR(Lq-MeF%G>-t(^o1vd4*bLE!ayWQ{(ig7-=&jhUw9l zOB{*mv$A;-9x^x6zJ{GK%c@k~8MDq(rcF0UN0`ds`jK~jodoH*8OpE>6q(5%GQ#EY zTSKUroERB0FYHVG{8(hM8y&O|uY4)4!a*3@%!f7{g{5ueLCXKsFm-2Sj*049R#D=6 NaOk6yJt0 Date: Mon, 2 Oct 2017 20:28:56 +0200 Subject: [PATCH 0411/1326] Add test for U+0A51 New Indic numbers are: BENGALI: 353725 out of 354188 tests passed. 463 failed (0.130722%) DEVANAGARI: 707307 out of 707394 tests passed. 87 failed (0.0122987%) GUJARATI: 366355 out of 366457 tests passed. 102 failed (0.0278341%) GURMUKHI: 60729 out of 60747 tests passed. 18 failed (0.0296311%) KANNADA: 951201 out of 951913 tests passed. 712 failed (0.0747968%) KHMER: 299071 out of 299124 tests passed. 53 failed (0.0177184%) MALAYALAM: 1048136 out of 1048334 tests passed. 198 failed (0.0188871%) ORIYA: 42320 out of 42329 tests passed. 9 failed (0.021262%) SINHALA: 271662 out of 271847 tests passed. 185 failed (0.068053%) TAMIL: 1091754 out of 1091754 tests passed. 0 failed (0%) TELUGU: 970555 out of 970573 tests passed. 18 failed (0.00185457%) Before 71c0a1429db7c7e7e32507be248c9457e1cbfc7d GURMUKHI used to be at 15, because Uniscribe seems to allow this character standalone, but that looks wrong. --- .../1735326da89f0818cd8c51a0600e9789812c0f94.ttf | Bin 0 -> 1008 bytes test/shaping/tests/indic-syllable.tests | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 test/shaping/fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf diff --git a/test/shaping/fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf b/test/shaping/fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b1e4cdbbe33b8bf142f1f0cfca6e22490e11ab4e GIT binary patch literal 1008 zcmaiz-%FEG7{|ZwkL{gqsi_Q#{mQf=Bw^DDZbANPU4*kn&_$3h>NaiDp&P8LN~){K zuA(l20nJ{&)g=;37XK*TfQMx)%3+Tp)iS2jYpA;MDT;O+e0&2L`ix zuJi1#I`SO3HKkAHps_=_L3X7w7nApwPWDm%$?tc1SRZnP=a=cPlEY~ls@t?C@(FTd zI-4&#zLnpTqhwcRd{D<;6alG3c4YNp4j!q7{D~YG)3d|s>aG^%BceYyKAE2`+JBJy z$sLf5nT;v@pIt)lj;vD76UU6_~dNe;<1$}AYgXXT;l zWlSxzH{dXWT&ss!>+Sm++FHY*pxah2v`}zM*8PWVRwyIoUa!Byut zNF=%uHdQfLR%4Z}9e%I!-RF(?Jf5p!ip_Xs$!+BU9U@+c+A6rsGZa}xLEBB;WO1Kj zM$#T%YB$vL)zK9=9j4#A%F-L5EZDCV*Jn$Mu1>9)SOM9bhWZvS0Aoh2=N)kkt-16R zaDG{zHLkllcjOa0QPoG%E!Y6tU0aB2JhP-cg`|9iRd(8B)uzgP4VxLPJU}cSkKtJ5 zsirwAht{m{{;dq^nz}|kU>05C$er-CDh^TFDJ94vvRr1_O}X-9F>J-sgK6OtQECNk zjbuxg`ByZe597%53m^dOoYA9RFtV7tl7ZJOBUy literal 0 HcmV?d00001 diff --git a/test/shaping/tests/indic-syllable.tests b/test/shaping/tests/indic-syllable.tests index 5b0ae90aa..3b5d1ebeb 100644 --- a/test/shaping/tests/indic-syllable.tests +++ b/test/shaping/tests/indic-syllable.tests @@ -3,3 +3,5 @@ fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF1:[gid1=0+1129] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF2:[gid2=0+1539] fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf::U+0980,U+0981:[anjibeng=0+520|candrabindubeng=0+0] fonts/sha1sum/85fe0be440c64ac77699e21c2f1bd933a919167e.ttf::U+0A15,U+0A51,U+0A47:[kaguru=0+1273|udaatguru=0@75,0+0|eematraguru=0@-40,0+0] +fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf::U+0A51:[uni25CC=0+1044|udaatguru=0+0] +fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf::U+25CC,U+0A51:[uni25CC=0+1044|udaatguru=0+0] From bbe94777c94637da1bcf944124b5079662618a1e Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Mon, 2 Oct 2017 22:36:14 +0200 Subject: [PATCH 0412/1326] Print test-suite.log when CI builds fail --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1b150584e..70e5fa688 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ script: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --with-coretext"; fi - ./configure $CONFIGURE_OPTS - make - - make check + - make check || (cat test/*/test-suite.log && false) - if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SLUG" == "behdad/harfbuzz" ]; then rm -f src/.libs/NONE.gcov; touch src/NONE; coveralls -e docs; fi after_success: - if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SECURE_ENV_VARS" == "true" ]; then bash .ci/deploy-docs.sh; fi diff --git a/appveyor.yml b/appveyor.yml index 05a371a69..49d741ed7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,7 +65,7 @@ build_script: - 'if "%compiler%"=="nmake" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 install' # FREETYPE=1 install' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || (cat test/*/test-suite.log && false)"' # disable automatic tests test: off From c44657a05d565ec5f2c32ac15d4ecfbee00ac5f7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 13:14:17 +0200 Subject: [PATCH 0413/1326] Tweak input matching some more Followup to 8b2c94c43fd335b944d5e5487265706b8e0f9041 Allow matching sequences of marks attached to different ligatures, as supposedly the base of the subsequent marks were already jumped over. --- src/hb-ot-layout-gsubgpos-private.hh | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index f2ad9f1c9..aa0862ad2 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -781,9 +781,6 @@ static inline bool match_input (hb_apply_context_t *c, * component, otherwise we shouldn't ligate them... */ if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) { - if (first_lig_id != this_lig_id && this_lig_id != 0) - return_trace (false); - /* ...unless, we are attached to a base ligature and that base * ligature is ignorable. */ bool found = false; From 09cbeb2246217dce61ccc0638edb6211facca4b0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 13:22:07 +0200 Subject: [PATCH 0414/1326] Make bots happy Fixes https://github.com/behdad/harfbuzz/issues/551 --- test/shaping/tests/indic-syllable.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shaping/tests/indic-syllable.tests b/test/shaping/tests/indic-syllable.tests index 3b5d1ebeb..500fa84bd 100644 --- a/test/shaping/tests/indic-syllable.tests +++ b/test/shaping/tests/indic-syllable.tests @@ -1,7 +1,7 @@ fonts/sha1sum/54674a3111d209fb6be0ed31745314b7a8d2c244.ttf::U+0BA4,U+0BCD,U+00B3:[taprehalftamil=0+1509|uni00B3=2+674] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF1:[gid1=0+1129] fonts/sha1sum/3d0b77a2360aa6faa1385aaa510509ab70dfbeff.ttf::U+0CF2:[gid2=0+1539] -fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf::U+0980,U+0981:[anjibeng=0+520|candrabindubeng=0+0] +fonts/sha1sum/87f85d17d26f1fe9ad28d7365101958edaefb967.ttf:--font-funcs=ot:U+0980,U+0981:[gid1=0+520|gid2=0+0] fonts/sha1sum/85fe0be440c64ac77699e21c2f1bd933a919167e.ttf::U+0A15,U+0A51,U+0A47:[kaguru=0+1273|udaatguru=0@75,0+0|eematraguru=0@-40,0+0] fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf::U+0A51:[uni25CC=0+1044|udaatguru=0+0] fonts/sha1sum/1735326da89f0818cd8c51a0600e9789812c0f94.ttf::U+25CC,U+0A51:[uni25CC=0+1044|udaatguru=0+0] From 771970efa15fc0b77841b7f0a3e266cdcf51246e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 13:23:31 +0200 Subject: [PATCH 0415/1326] Minor --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 70e5fa688..fd2139ae7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ script: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export CONFIGURE_OPTS="$CONFIGURE_OPTS --with-coretext"; fi - ./configure $CONFIGURE_OPTS - make - - make check || (cat test/*/test-suite.log && false) + - make check || (cat */test-suite.log test/*/test-suite.log && false) - if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SLUG" == "behdad/harfbuzz" ]; then rm -f src/.libs/NONE.gcov; touch src/NONE; coveralls -e docs; fi after_success: - if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" == "gcc" -a "$TRAVIS_SECURE_ENV_VARS" == "true" ]; then bash .ci/deploy-docs.sh; fi diff --git a/appveyor.yml b/appveyor.yml index 49d741ed7..3d3f77742 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,7 +65,7 @@ build_script: - 'if "%compiler%"=="nmake" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 install' # FREETYPE=1 install' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || (cat test/*/test-suite.log && false)"' + - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || (cat */test-suite.log test/*/test-suite.log && false)"' # disable automatic tests test: off From 5d98de1f382254a8a21fd9a04b642268a21be16f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 13:46:25 +0200 Subject: [PATCH 0416/1326] Tweak mark-base attachment Apparently a base glyph can also become an attached component of a ligature if the ligature-forming lookup used IgnoreBase. This was being confused with a non-first component of a MultipleSubst and hence not matched for mark-attachment. Tweak test to fix. Fixes https://github.com/behdad/harfbuzz/issues/543 --- src/hb-ot-layout-gpos-table.hh | 4 +++- test/shaping/Makefile.am | 1 + .../98b7887cff91f722b92a8ff800120954606354f9.ttf | Bin 0 -> 1168 bytes test/shaping/tests/mark-attachment.tests | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test/shaping/fonts/sha1sum/98b7887cff91f722b92a8ff800120954606354f9.ttf create mode 100644 test/shaping/tests/mark-attachment.tests diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 738ca8c44..e45ce2721 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1087,7 +1087,9 @@ struct MarkBasePosFormat1 do { if (!skippy_iter.prev ()) return_trace (false); /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */ - if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break; + if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || + 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) + break; skippy_iter.reject (); } while (1); diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index 6617e679c..d56bcc4c3 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -62,6 +62,7 @@ TESTS = \ tests/indic-syllable.tests \ tests/language-tags.tests \ tests/ligature-id.tests \ + tests/mark-attachment.tests \ tests/mark-filtering-sets.tests \ tests/mongolian-variation-selector.tests \ tests/spaces.tests \ diff --git a/test/shaping/fonts/sha1sum/98b7887cff91f722b92a8ff800120954606354f9.ttf b/test/shaping/fonts/sha1sum/98b7887cff91f722b92a8ff800120954606354f9.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4835c762378fa2a51a8ff8a1c40e290464693dcd GIT binary patch literal 1168 zcmZuwO-NKx6#njgGiv^hKecEfBbJ*4$2Tc1hBALCElrcgAZyam5odJp2NjHhc0v$g zvuafvk%9=?wGbCED{Etmh-lHmHVuSAi}dxK`zEyTKJL5cJLkLSe&@XVpa2x%J}mTh zwzYR4gi^p-qPMoQx2Jz4^>m$hmH2UI|3J%!fp5EjCq&%W(_d#V6wD_8eU|w4a3YfQ zzw|#LULo!ti!Y8|c(^9q&z!Gg(a1>Q+K;<{S|@Id(cyjJJR{#nd@7chUGUt)8ODDR zpNLNlN3e!z;#b7QiO52d>MjvKBKA*45>YE$@P+%o5;rHOW@ZPYeb1@aPkaLkHn}@$ z2f0A7w5n9*h#Io@X0o&7@LI8Az)JIE=oI$l-EY3uObCtb6*YWeNoOH85DP5Xs<*(h>1xosQe1EAfRaKhH>0YnnunM(LAVDtGbbX`6Y|f6f$R zk&5%V`glvP3fp!= literal 0 HcmV?d00001 diff --git a/test/shaping/tests/mark-attachment.tests b/test/shaping/tests/mark-attachment.tests new file mode 100644 index 000000000..c3c2d2784 --- /dev/null +++ b/test/shaping/tests/mark-attachment.tests @@ -0,0 +1 @@ +fonts/sha1sum/98b7887cff91f722b92a8ff800120954606354f9.ttf::U+100F,U+103C,U+102F,U+1036:[uni103C102F=0+150|uni100F=0+550|uni1036=0@-150,0+0] From 3ca9c92aa68956889642690e176c9161ff52edfe Mon Sep 17 00:00:00 2001 From: David Corbett Date: Tue, 3 Oct 2017 08:07:02 -0400 Subject: [PATCH 0417/1326] Test Consonant_With_Stacker in Kannada (#530) --- test/shaping/Makefile.am | 1 + test/shaping/fonts/COPYING | 100 ++++++++++++++++++ ...1421e629668b1a1242245d39238ca48432d35d.ttf | Bin 0 -> 1084 bytes ...c88ebbe938680b08f92c3de20713183e0c7481.ttf | Bin 0 -> 3300 bytes ...3aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf | Bin 0 -> 1204 bytes ...14549f766436cf55b2ceb40e462038938ee899.ttf | Bin 0 -> 2720 bytes .../tests/indic-consonant-with-stacker.tests | 4 + 7 files changed, 105 insertions(+) create mode 100644 test/shaping/fonts/COPYING create mode 100644 test/shaping/fonts/sha1sum/341421e629668b1a1242245d39238ca48432d35d.ttf create mode 100644 test/shaping/fonts/sha1sum/55c88ebbe938680b08f92c3de20713183e0c7481.ttf create mode 100644 test/shaping/fonts/sha1sum/663aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf create mode 100644 test/shaping/fonts/sha1sum/a014549f766436cf55b2ceb40e462038938ee899.ttf create mode 100644 test/shaping/tests/indic-consonant-with-stacker.tests diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index d56bcc4c3..d29800c45 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -55,6 +55,7 @@ TESTS = \ tests/fuzzed.tests \ tests/hangul-jamo.tests \ tests/hyphens.tests \ + tests/indic-consonant-with-stacker.tests \ tests/indic-joiner-candrabindu.tests \ tests/indic-joiners.tests \ tests/indic-old-spec.tests \ diff --git a/test/shaping/fonts/COPYING b/test/shaping/fonts/COPYING new file mode 100644 index 000000000..87faaca0a --- /dev/null +++ b/test/shaping/fonts/COPYING @@ -0,0 +1,100 @@ +The following license applies to these fonts: + + sha1sum/341421e629668b1a1242245d39238ca48432d35d.ttf + sha1sum/55c88ebbe938680b08f92c3de20713183e0c7481.ttf + sha1sum/663aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf + sha1sum/a014549f766436cf55b2ceb40e462038938ee899.ttf + + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/test/shaping/fonts/sha1sum/341421e629668b1a1242245d39238ca48432d35d.ttf b/test/shaping/fonts/sha1sum/341421e629668b1a1242245d39238ca48432d35d.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5b82bb570a50235ea6d57cbd76f1716597ac1687 GIT binary patch literal 1084 zcmZWoUuaWT82{aybK|wWX{sh7w2gOj6JgS|D#Gffwe6Bgq1Pqe__ld5F{viGp-EjT zf^LX{7ev_0TGaMsV@)0kGWIf&$p*go2T`9y5FOhXW6=E}*Cpooo!qhwb`IxvzTfxn zeD^!|7zYj*&~O?)439>m`uga-D*$c*(u3I8yHNxo1M&jtLb3fu0%3Fz|BAR4OPC`o z{9D0|#GBhrth*2AMr1eQb2qYvrTLaM7Foc1pM1<6=N~~^)f#Et?*jt!1pbOr zPXuS(-!3a z`}MuKoE{gZk{(Z&(o@INseVzME~?X4${VrmW7KX5(mBYIBsaR6OV8hMpM>3B_qcPj zb;@xJcXRV}^R4EbWBmP%x2P;4PsXs@5E}Ui5S9GEIkLi<#t*gilz2T&>N_R5<^oTKkCepG;G2M4KOk>&eC$ zg`-ELdF(kSIsaKC44URCaWsh(%=r((ObIiN+IZwY=y(C`!})K*pK@wQYTOwo!XjSQxdBYCPFEpmcBiQd@%$4lK%D(wIO literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/55c88ebbe938680b08f92c3de20713183e0c7481.ttf b/test/shaping/fonts/sha1sum/55c88ebbe938680b08f92c3de20713183e0c7481.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f6540674967a05628aaa1b5d0d6f8e7b6e2401d0 GIT binary patch literal 3300 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 JU*P|*{{UK6CL#a; literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/663aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf b/test/shaping/fonts/sha1sum/663aef6b019dbf45ffd74089e2b5f2496ceceb18.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8f7fda506b4967a01a12be8bbd8629a3d0029fc1 GIT binary patch literal 1204 zcmZWoO>7%Q7=62*HH&}Zw2dXCHts@+giJ}(G=eG$Rf*G>s3K17POh+O+_;Us8^sPX zg+mGm5Gx`6iWCln0~gj(QG4jAP*t>t&=gQhq_!6-^?*Pik^U%d9eMa>H$Mkvv~S;= z_kG`dYtLj3AI>0x83eFDH8^PSrOxDbb)VSsQJnk%(ytvUnUjb_50L(bbWb5~j)j-Ly-)fE>E{cy&|1_DfVGl- zx=^ZAL%%AFbPs90WL77kju2&i1VPIz<=M}XbEIYc;Yqt(5dj<}{W)nv0b@`UrFGb@ z*g4ZGA2cn?95dzGKz$qP?MgkN))RsHcGfT>fu#sbe2tgiJ}De$okSjM_BXG$1JOBx zU{zbr#b%e^*}Ocu37Vqlv3;4`v~{d2HQ2qov#ZCLE~MQq_7b-?~*X}(=+P24w zd1J^r(rLU@EE-v9m5pq^oS%9nD;jO&8>Ykac1Jon*u##2&CjP`ehHXMSg*j zB<=9h*V%JPS75W0y(yA_1B7)72d-|q^P_w({!;m2CEK_doeNe; z>fR30plW_E(X%Vr=K1K{YCY-sLuFTSF&ID!pt~tMlbDd5vBxR;DbhYy(L!n%HY)TO j$iak#GO>dmvk1rN$s&(&OruDA%FC8DL7zl-`~TxVp`l{O literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/a014549f766436cf55b2ceb40e462038938ee899.ttf b/test/shaping/fonts/sha1sum/a014549f766436cf55b2ceb40e462038938ee899.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9a34ba51b1a188df3bdcae9d6235137e5641d121 GIT binary patch literal 2720 zcmZuze{dXC9sllT@3>wrNkenBEun6b65At_rb(!_6bea9#I!w3`T{eKgtJMLz~%1f zUDCvkihciHx0V+~krfG5R+CB31^L?B4 z>ge0q@B9A#_1@dJ(VaV^6rwq*pxe58d+i@Saj=<)UMBK?y|3q!y%Z*k=$gC1Th(`G zbg=LIhVO&UfPS)XP<8z+^!gd1Kpm0cj}ESH|H86I!bD5zA-{LmWGq!R9D@FmeW16D zkH$tS=MQ}V`j?t_zJT%j}=c`Tliuv1q>rl({y8d zY|r#mVxp~k(@lEn-LOav>$$t9_4Dz)yT{_Qsqv1sk8fyg>$IoFyOXKeJriT&8N0o0 zLxo~`Kr9&653%gqj<38qpWOGcb0r*Td%Tx!z=YULv+Fd%xrFUc82+MHn*4gU8MqUZ|RR$8?>zIq4}6G5=E> z)+qI$ga!&@=66I4hht8_ecgYT;~D7S{JtpYgqDlGj<`appZu7~&gKHu^_Si%9COcv z8-s3of4C{=e!6fj{HW^-S1-I*eDA}S|0BRcTi>aZ<$fsq*fO%vUE`wpRK-`UjnAOS zILdv4sVahSH%Vrz1eCGnJj!pBWRS;^%P=JBt#jo3+F|N~l+TOVEz;U|MEMiKD`T&U z^yX}Kkm**`;jU~)v+fq1Ln3KWs?%Y93b`=9A?!i~;O#uR`My%qm*FYl&gaz_b1|Fq zAoK6VpaehsE3827Nme! z+uHjL+Ixdib3dPAT7&Lao<-1pr9gIObHkUREIc38jrxVy@L@RNQ+aTYMNr@$gv<*l zV~3FtpB9zJwTTDCkiwDNT}%ICOPZ@9xtF9~penzj-qldTkeIy+HCH2oOz{s zoqlIKj_mK0!XEgO?84*j3V&hcH?jD?75l%!Ex#$?7@Tf(n2(4reWqWO&TkYgy_L(@ zHqrlABzM-ifIOn2RyRjS4<9`YOQAOBO7o+)J6A@ucvq0PHGt$osLn9&ehhr+VNN>K`mEh zEEQrbW^bm_nKV^vD0jJJA(co>3%*y-PWrCqd3o93`?a3bb}i)cNZzC~6?=J1JTiOT z6rb|q!>y|m+g@5qt6(E_HbW}i@oc?bc-{POdy!o3kpGG{E(Kqc@h$QZ`40Fxps>%I z&2P|db2G}R^qH2=GEIwagZ)*bFB<@*81&24bD7b)WC6WaE+QBpaFQ z07Y7d%JjdEuFwp9FEo#ik~d$7U#RtbKvT4h;4Les-rYM~v*q7ZDO-i;MD5!z$ee#A z^PAFu`+U_w{|rd!j5lEC Date: Tue, 3 Oct 2017 14:57:14 +0200 Subject: [PATCH 0418/1326] [use] Implement Consonant_With_Stacker Related to https://github.com/behdad/harfbuzz/issues/528 --- src/gen-use-table.py | 7 ++++--- src/hb-ot-shape-complex-use-machine.rl | 5 +++-- src/hb-ot-shape-complex-use-private.hh | 3 ++- src/hb-ot-shape-complex-use-table.cc | 6 ++++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gen-use-table.py b/src/gen-use-table.py index 4f4826125..09cc64fa6 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -178,6 +178,8 @@ def is_CONS_MOD(U, UISC, UGC): def is_CONS_SUB(U, UISC, UGC): #SPEC-DRAFT return UISC == Consonant_Subjoined return UISC == Consonant_Subjoined and UGC != Lo +def is_CONS_WITH_STACKER(U, UISC, UGC): + return UISC == Consonant_With_Stacker def is_HALANT(U, UISC, UGC): return UISC in [Virama, Invisible_Stacker] def is_HALANT_NUM(U, UISC, UGC): @@ -199,9 +201,7 @@ def is_OTHER(U, UISC, UGC): def is_Reserved(U, UISC, UGC): return UGC == 'Cn' def is_REPHA(U, UISC, UGC): - #return UISC == Consonant_Preceding_Repha - #SPEC-OUTDATED hack to categorize Consonant_With_Stacker and Consonant_Prefixed - return UISC in [Consonant_Preceding_Repha, Consonant_With_Stacker, Consonant_Prefixed] + return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed] def is_SYM(U, UISC, UGC): if U == 0x25CC: return False #SPEC-DRAFT #SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter @@ -230,6 +230,7 @@ use_mapping = { 'M': is_CONS_MED, 'CM': is_CONS_MOD, 'SUB': is_CONS_SUB, + 'CS': is_CONS_WITH_STACKER, 'H': is_HALANT, 'HN': is_HALANT_NUM, 'ZWNJ': is_ZWNJ, diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl index 2a7f75115..7bd8fce15 100644 --- a/src/hb-ot-shape-complex-use-machine.rl +++ b/src/hb-ot-shape-complex-use-machine.rl @@ -86,6 +86,7 @@ VMPst = 39; # VOWEL_MOD_POST VMPre = 23; # VOWEL_MOD_PRE SMAbv = 41; # SYM_MOD_ABOVE SMBlw = 42; # SYM_MOD_BELOW +CS = 43; # CONS_WITH_STACKER consonant_modifiers = CMAbv* CMBlw* ((H B | SUB) VS? CMAbv? CMBlw*)*; @@ -96,12 +97,12 @@ vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*; final_consonants = FAbv* FBlw* FPst* FM?; virama_terminated_cluster = - R? (B | GB) VS? + (R|CS)? (B | GB) VS? consonant_modifiers H ; standard_cluster = - R? (B | GB) VS? + (R|CS)? (B | GB) VS? consonant_modifiers medial_consonants dependent_vowels diff --git a/src/hb-ot-shape-complex-use-private.hh b/src/hb-ot-shape-complex-use-private.hh index ae428cb5e..3e763ae39 100644 --- a/src/hb-ot-shape-complex-use-private.hh +++ b/src/hb-ot-shape-complex-use-private.hh @@ -87,7 +87,8 @@ enum use_category_t { USE_VMPst = 39, /* VOWEL_MOD_POST */ USE_VMPre = 23, /* VOWEL_MOD_PRE */ USE_SMAbv = 41, /* SYM_MOD_ABOVE */ - USE_SMBlw = 42 /* SYM_MOD_BELOW */ + USE_SMBlw = 42, /* SYM_MOD_BELOW */ + USE_CS = 43 /* CONS_WITH_STACKER */ }; HB_INTERNAL USE_TABLE_ELEMENT_TYPE diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index daae04ed3..1f90fc858 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -19,6 +19,7 @@ #define B USE_B /* BASE */ #define CGJ USE_CGJ /* CGJ */ +#define CS USE_CS /* CONS_WITH_STACKER */ #define FM USE_FM /* CONS_FINAL_MOD */ #define GB USE_GB /* BASE_OTHER */ #define H USE_H /* HALANT */ @@ -163,7 +164,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O, /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0CF0 */ O, CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Malayalam */ @@ -467,7 +468,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* Brahmi */ - /* 11000 */ VMPst, VMAbv, VMPst, R, R, B, B, B, B, B, B, B, B, B, B, B, + /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B, /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, @@ -729,6 +730,7 @@ hb_use_get_categories (hb_codepoint_t u) #undef B #undef CGJ +#undef CS #undef FM #undef GB #undef H From f559c633073f63b9d87cb2440048b4413cfa1c05 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 15:20:07 +0200 Subject: [PATCH 0419/1326] [indic] Implement Consonent_With_Stacker Fixes https://github.com/behdad/harfbuzz/issues/528 --- src/hb-ot-shape-complex-indic-machine.rl | 5 +++-- src/hb-ot-shape-complex-indic-private.hh | 7 ++++--- src/hb-ot-shape-complex-myanmar-machine.rl | 5 +++-- src/hb-ot-shape-complex-myanmar.cc | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl index 86a7ceb22..58d35c001 100644 --- a/src/hb-ot-shape-complex-indic-machine.rl +++ b/src/hb-ot-shape-complex-indic-machine.rl @@ -57,6 +57,7 @@ Repha = 15; Ra = 16; CM = 17; Symbol= 18; +CS = 19; c = (C | Ra); # is_consonant n = ((ZWNJ?.RS)? (N.N?)?); # is_consonant_modifier @@ -76,9 +77,9 @@ medial_group = CM?; halant_or_matra_group = (final_halant_group | (h.ZWJ)? matra_group{0,4}) (Coeng (cn|V))?; -consonant_syllable = Repha? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail; +consonant_syllable = (Repha|CS)? (cn.halant_group){0,4} cn medial_group halant_or_matra_group syllable_tail; vowel_syllable = reph? V.n? (ZWJ | (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail); -standalone_cluster = (Repha? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail; +standalone_cluster = ((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail; symbol_cluster = symbol syllable_tail; broken_cluster = reph? n? (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail; other = any; diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh index c880311ee..8263bc808 100644 --- a/src/hb-ot-shape-complex-indic-private.hh +++ b/src/hb-ot-shape-complex-indic-private.hh @@ -60,7 +60,8 @@ enum indic_category_t { OT_Repha = 15, /* Atomically-encoded logical or visual repha. */ OT_Ra = 16, OT_CM = 17, /* Consonant-Medial. */ - OT_Symbol = 18 /* Avagraha, etc that take marks (SM,A,VD). */ + OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */ + OT_CS = 19 }; #define MEDIAL_FLAGS (FLAG (OT_CM)) @@ -70,7 +71,7 @@ enum indic_category_t { * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels * cannot happen in a consonant syllable. The plus side however is, we can call the * consonant syllable logic from the vowel syllable function and get it all right! */ -#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE)) +#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE)) #define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) #define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) @@ -121,7 +122,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, - INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS, INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl index 9649a916f..45733ac73 100644 --- a/src/hb-ot-shape-complex-myanmar-machine.rl +++ b/src/hb-ot-shape-complex-myanmar-machine.rl @@ -41,7 +41,7 @@ A = 10; As = 18; C = 1; -D = 19; +D = 32; D0 = 20; DB = 3; GB = 11; @@ -62,6 +62,7 @@ ZWJ = 6; ZWNJ = 5; Ra = 16; P = 31; +CS = 19; j = ZWJ|ZWNJ; # Joiners k = (Ra As H); # Kinzi @@ -76,7 +77,7 @@ pwo_tone_group = PT A* DB? As?; complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?; syllable_tail = (H | complex_syllable_tail); -consonant_syllable = k? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail; +consonant_syllable = (k|CS)? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail; punctuation_cluster = P V; broken_cluster = k? VS? syllable_tail; other = any; diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index ebd2b4096..676d4948c 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -130,8 +130,7 @@ enum syllable_type_t { /* Note: This enum is duplicated in the -machine.rl source file. * Not sure how to avoid duplication. */ enum myanmar_category_t { - OT_As = 18, /* Asat */ - OT_D = 19, /* Digits except zero */ + OT_As = 18, /* Asat */ OT_D0 = 20, /* Digit zero */ OT_DB = OT_N, /* Dot below */ OT_GB = OT_PLACEHOLDER, @@ -145,7 +144,8 @@ enum myanmar_category_t { OT_VPre = 28, OT_VPst = 29, OT_VS = 30, /* Variation selectors */ - OT_P = 31 /* Punctuation */ + OT_P = 31, /* Punctuation */ + OT_D = 32, /* Digits except zero */ }; From 63db692fa9efcd760f2e90f93f4e1428d79a3433 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 16:00:18 +0200 Subject: [PATCH 0420/1326] [indic] Fix shaping of U+0AFB GUJARATI SIGN SHADDA Fixes https://github.com/behdad/harfbuzz/issues/552 --- src/hb-ot-shape-complex-indic-private.hh | 2 +- src/hb-ot-shape-complex-indic.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh index 8263bc808..8fe2509ef 100644 --- a/src/hb-ot-shape-complex-indic-private.hh +++ b/src/hb-ot-shape-complex-indic-private.hh @@ -123,7 +123,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS, - INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, + INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, /* https://github.com/behdad/harfbuzz/issues/552 */ INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index d16816016..00130e6c2 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -220,6 +220,8 @@ set_indic_properties (hb_glyph_info_t &info) else if (unlikely (u == 0x11303u)) cat = OT_SM; else if (unlikely (u == 0x1133cu)) cat = OT_N; + else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/behdad/harfbuzz/issues/552 */ + else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/behdad/harfbuzz/issues/538 */ else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) From 9786fcd8fdc0adbe8b6269ddd174ee2818d6fa9e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 3 Oct 2017 17:22:43 +0200 Subject: [PATCH 0421/1326] Fix GPOS v_origin ordering This should affect mark attachment in vertical text. I have no font to test, but this sounds the right order. Noticed while debugging https://github.com/behdad/harfbuzz/issues/532 --- src/hb-ot-shape.cc | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 8cd8fcc17..8fc9d464f 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -693,9 +693,9 @@ hb_ot_position_default (hb_ot_shape_context_t *c) static inline void hb_ot_position_complex (hb_ot_shape_context_t *c) { - hb_ot_layout_position_start (c->font, c->buffer); - unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; /* If the font has no GPOS, AND, no fallback positioning will * happen, AND, direction is forward, then when zeroing mark @@ -710,6 +710,17 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) !c->plan->shaper->fallback_position && HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); + /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ + + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->add_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + + hb_ot_layout_position_start (c->font, c->buffer); + switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: @@ -723,30 +734,8 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) } if (likely (!c->fallback_positioning)) - { - hb_glyph_info_t *info = c->buffer->info; - hb_glyph_position_t *pos = c->buffer->pos; - - /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ - - /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ - if (c->font->has_glyph_h_origin_func ()) - for (unsigned int i = 0; i < count; i++) - c->font->add_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - c->plan->position (c->font, c->buffer); - /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ - if (c->font->has_glyph_h_origin_func ()) - for (unsigned int i = 0; i < count; i++) - c->font->subtract_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - - } - switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: @@ -763,6 +752,13 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c); hb_ot_layout_position_finish_offsets (c->font, c->buffer); + + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); } static inline void From 50e95229d79bd258ad1d3f6392bfffa128f6df2a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 11:28:04 +0200 Subject: [PATCH 0422/1326] Add Chinantec language tags Fixes https://github.com/behdad/harfbuzz/issues/516 --- src/hb-ot-tag.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index 9b0db507b..f3671babe 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -270,28 +270,36 @@ static const LangTag ot_languages[] = { {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */ {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */ + {"cco", HB_TAG('C','C','H','N')}, /* Chinantec */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ {"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */ {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ + {"chj", HB_TAG('C','C','H','N')}, /* Chinantec */ {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ + {"chq", HB_TAG('C','C','H','N')}, /* Chinantec */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"chz", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */ {"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */ {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */ {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */ + {"cle", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */ {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */ {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */ {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */ + {"cnl", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"cnt", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ + {"cpa", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ {"cre", HB_TAG('Y','C','R',' ')}, /* Y-Cree */ @@ -302,15 +310,21 @@ static const LangTag ot_languages[] = { {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ + {"csa", HB_TAG('C','C','H','N')}, /* Chinantec */ {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */ + {"cso", HB_TAG('C','C','H','N')}, /* Chinantec */ {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */ {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */ + {"cte", HB_TAG('C','C','H','N')}, /* Chinantec */ {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ + {"ctl", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ + {"cuc", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cuk", HB_TAG('C','U','K',' ')}, /* San Blas Kuna */ {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ + {"cvn", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */ {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */ From d695cacbf4dd5f77b5e7134cf60553775c515ef1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 11:33:47 +0200 Subject: [PATCH 0423/1326] Shorthand format controls should not be ignored Fixes https://github.com/behdad/harfbuzz/issues/503 --- src/hb-unicode-private.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index 34513e132..cd6c67c87 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -141,6 +141,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * we do NOT want to hide them, as the way Uniscribe has implemented them * is with regular spacing glyphs, and that's the way fonts are made to work. * As such, we make exceptions for those four. + * Also ignoring U+1BCA0..1BCA3. https://github.com/behdad/harfbuzz/issues/503 * * Unicode 7.0: * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/' @@ -197,8 +198,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE { /* Other planes */ switch (plane) { - case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u, - 0x1D173u, 0x1D17Au); + case 0x01: return hb_in_range (ch, 0x1D173u, 0x1D17Au); case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu); default: return false; } From 4c05a405acc25c4ef0d70a97c0ae59013abca2df Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 13:06:51 +0200 Subject: [PATCH 0424/1326] Revert "Treat HAMZA ABOVE similar to SHADD for sorting purposes" This reverts commit 5a330575768f5a213072230b9ec8faabac9c5737. Proper fix coming soon. --- src/hb-unicode-private.hh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index cd6c67c87..eaa12d8f7 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -105,10 +105,6 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE inline unsigned int modified_combining_class (hb_codepoint_t unicode) { - /* XXX This hack belongs to the Arabic shaper: - * Put HAMZA ABOVE in the same class as SHADDA. */ - if (unlikely (unicode == 0x0654u)) unicode = 0x0651u; - /* XXX This hack belongs to the Myanmar shaper. */ if (unlikely (unicode == 0x1037u)) unicode = 0x103Au; From a252ad61f077c3b7bbfd8335e1b105a57beb58ce Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 13:07:08 +0200 Subject: [PATCH 0425/1326] Minor --- src/hb-unicode-private.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index eaa12d8f7..44a7471cf 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -108,7 +108,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE /* XXX This hack belongs to the Myanmar shaper. */ if (unlikely (unicode == 0x1037u)) unicode = 0x103Au; - /* XXX This hack belongs to the SEA shaper (for Tai Tham): + /* XXX This hack belongs to the USE shaper (for Tai Tham): * Reorder SAKOT to ensure it comes after any tone marks. */ if (unlikely (unicode == 0x1A60u)) return 254; From 7f9e7f8689e1d260596f5256947dfbd474afb1ec Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 13:20:33 +0200 Subject: [PATCH 0426/1326] Adjust normalizer for out-of-order marks We are going to implement Unicode Arabic Mark Ordering Algorithm: http://www.unicode.org/reports/tr53/tr53-1.pdf which will reorder marks out of their sorted ccc order. Adjust normalizer to stop combining as soon as dangerous ordering is detected. --- src/hb-ot-shape-normalize.cc | 60 +++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 94a3d7d27..63f1d2d33 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -369,46 +369,58 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->clear_output (); count = buffer->len; unsigned int starter = 0; + bool combine = true; buffer->next_glyph (); while (buffer->idx < count && !buffer->in_error) { hb_codepoint_t composed, glyph; - if (/* We don't try to compose a non-mark character with it's preceding starter. + if (combine && + /* We don't try to compose a non-mark character with it's preceding starter. * This is both an optimization to avoid trying to compose every two neighboring * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ - HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())) && - /* If there's anything between the starter and this char, they should have CCC - * smaller than this character's. */ - (starter == buffer->out_len - 1 || - _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) && - /* And compose. */ - c.compose (&c, - buffer->out_info[starter].codepoint, - buffer->cur().codepoint, - &composed) && - /* And the font has glyph for the composite. */ - font->get_nominal_glyph (composed, &glyph)) + HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) { - /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ - if (unlikely (buffer->in_error)) - return; - buffer->merge_out_clusters (starter, buffer->out_len); - buffer->out_len--; /* Remove the second composable. */ - /* Modify starter and carry on. */ - buffer->out_info[starter].codepoint = composed; - buffer->out_info[starter].glyph_index() = glyph; - _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + if (/* If there's anything between the starter and this char, they should have CCC + * smaller than this character's. */ + (starter == buffer->out_len - 1 || + _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) && + /* And compose. */ + c.compose (&c, + buffer->out_info[starter].codepoint, + buffer->cur().codepoint, + &composed) && + /* And the font has glyph for the composite. */ + font->get_nominal_glyph (composed, &glyph)) + { + /* Composes. */ + buffer->next_glyph (); /* Copy to out-buffer. */ + if (unlikely (buffer->in_error)) + return; + buffer->merge_out_clusters (starter, buffer->out_len); + buffer->out_len--; /* Remove the second composable. */ + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; + _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); - continue; + continue; + } + else if (/* We sometimes custom-tailor the sorted order of marks. In that case, stop + * trying to combine as soon as combining-class drops. */ + starter < buffer->out_len - 1 && + _hb_glyph_info_get_modified_combining_class (&buffer->prev()) > _hb_glyph_info_get_modified_combining_class (&buffer->cur())) + combine = false; } /* Blocked, or doesn't compose. */ buffer->next_glyph (); if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) + { starter = buffer->out_len - 1; + combine = true; + } } buffer->swap_buffers (); From b6fe0ab636ffac0a246e160b3508cc4841cb1823 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 13:37:08 +0200 Subject: [PATCH 0427/1326] Add info_cc() convenience macro --- src/hb-ot-layout-private.hh | 2 ++ src/hb-ot-shape-normalize.cc | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index d4ac60b06..6717adeb9 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -347,6 +347,8 @@ _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0; } +#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info))) + static inline bool _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info) { diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 63f1d2d33..a5144888a 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -384,7 +384,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (/* If there's anything between the starter and this char, they should have CCC * smaller than this character's. */ (starter == buffer->out_len - 1 || - _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) && + info_cc (buffer->prev()) < info_cc (buffer->cur())) && /* And compose. */ c.compose (&c, buffer->out_info[starter].codepoint, @@ -409,14 +409,14 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, else if (/* We sometimes custom-tailor the sorted order of marks. In that case, stop * trying to combine as soon as combining-class drops. */ starter < buffer->out_len - 1 && - _hb_glyph_info_get_modified_combining_class (&buffer->prev()) > _hb_glyph_info_get_modified_combining_class (&buffer->cur())) + info_cc (buffer->prev()) > info_cc (buffer->cur())) combine = false; } /* Blocked, or doesn't compose. */ buffer->next_glyph (); - if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) + if (info_cc (buffer->prev()) == 0) { starter = buffer->out_len - 1; combine = true; From ab8d70ec7023e51ba6fd7267d2b41c5f95ef0787 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 14:47:10 +0200 Subject: [PATCH 0428/1326] [arabic] Implement Unicode Arabic Mark Ordering Algorithm UTR#53 Fixes https://github.com/behdad/harfbuzz/issues/509 --- src/hb-ot-shape-complex-arabic.cc | 75 ++++++++++++++++++ src/hb-ot-shape-complex-default.cc | 1 + src/hb-ot-shape-complex-hangul.cc | 1 + src/hb-ot-shape-complex-hebrew.cc | 1 + src/hb-ot-shape-complex-indic.cc | 1 + src/hb-ot-shape-complex-myanmar.cc | 2 + src/hb-ot-shape-complex-private.hh | 12 +++ src/hb-ot-shape-complex-thai.cc | 1 + src/hb-ot-shape-complex-tibetan.cc | 1 + src/hb-ot-shape-complex-use.cc | 1 + src/hb-ot-shape-normalize.cc | 8 +- test/shaping/Makefile.am | 1 + ...b8d24d00ae86f49791b746da4c9d3f717a51a8.ttf | Bin 0 -> 7160 bytes ...a5d6fb15a27521fba9ea4aee9cb39b2d03322a.ttf | Bin 0 -> 6816 bytes test/shaping/record-test.sh | 2 +- test/shaping/tests/arabic-mark-order.tests | 2 + 16 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 test/shaping/fonts/sha1sum/24b8d24d00ae86f49791b746da4c9d3f717a51a8.ttf create mode 100644 test/shaping/fonts/sha1sum/94a5d6fb15a27521fba9ea4aee9cb39b2d03322a.ttf create mode 100644 test/shaping/tests/arabic-mark-order.tests diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index ed7b3f2dd..28dd4e1fe 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -613,6 +613,80 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } +/* http://www.unicode.org/reports/tr53/tr53-1.pdf */ + +static hb_codepoint_t +modifier_combining_marks[] = +{ + 0x0654u, /* ARABIC HAMZA ABOVE */ + 0x0655u, /* ARABIC HAMZA BELOW */ + 0x0658u, /* ARABIC MARK NOON GHUNNA */ + 0x06DCu, /* ARABIC SMALL HIGH SEEN */ + 0x06E3u, /* ARABIC SMALL LOW SEEN */ + 0x06E7u, /* ARABIC SMALL HIGH YEH */ + 0x06E8u, /* ARABIC SMALL HIGH NOON */ + 0x08F3u, /* ARABIC SMALL HIGH WAW */ +}; + +static inline bool +info_is_mcm (const hb_glyph_info_t &info) +{ + hb_codepoint_t u = info.codepoint; + for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++) + if (u == modifier_combining_marks[i]) + return true; + return false; +} + +static void +reorder_marks_arabic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, + unsigned int end) +{ + hb_glyph_info_t *info = buffer->info; + + unsigned int i = start; + for (unsigned int cc = 220; cc <= 230; cc += 10) + { + DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d\n", cc, i); + while (i < end && info_cc(info[i]) < cc) + i++; + DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d\n", cc, i); + + if (i == end) + break; + + if (info_cc(info[i]) > cc) + continue; + + /* Technically we should also check "info_cc(info[j]) == cc" + * in the following loop. But not doing it is safe; we might + * end up moving all the 220 MCMs and 230 MCMs together in one + * move and be done. */ + unsigned int j = i; + while (j < end && info_is_mcm (info[j])) + j++; + DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d\n", cc, i, j); + + if (i == j) + continue; + + /* Shift it! */ + DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d\n", cc, i, j); + hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS]; + assert (j - i <= ARRAY_LENGTH (temp)); + buffer->merge_out_clusters (start, j); + memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t)); + memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t)); + memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t)); + + start += j - i; + + i = j; + } +} + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = { "arabic", @@ -627,6 +701,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = NULL, /* compose */ setup_masks_arabic, NULL, /* disable_otl */ + reorder_marks_arabic, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-default.cc b/src/hb-ot-shape-complex-default.cc index 42830ab61..857980cfc 100644 --- a/src/hb-ot-shape-complex-default.cc +++ b/src/hb-ot-shape-complex-default.cc @@ -41,6 +41,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = NULL, /* compose */ NULL, /* setup_masks */ NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc index 0e74802ee..63850d36a 100644 --- a/src/hb-ot-shape-complex-hangul.cc +++ b/src/hb-ot-shape-complex-hangul.cc @@ -426,6 +426,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = NULL, /* compose */ setup_masks_hangul, NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-hebrew.cc b/src/hb-ot-shape-complex-hebrew.cc index 96f249461..b8ddadc1e 100644 --- a/src/hb-ot-shape-complex-hebrew.cc +++ b/src/hb-ot-shape-complex-hebrew.cc @@ -181,6 +181,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = compose_hebrew, NULL, /* setup_masks */ disable_otl_hebrew, + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 00130e6c2..31dc1c0eb 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1840,6 +1840,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = compose_indic, setup_masks_indic, NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index 676d4948c..4081ed03d 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc @@ -524,6 +524,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old = NULL, /* compose */ NULL, /* setup_masks */ NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; @@ -542,6 +543,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = NULL, /* compose */ setup_masks_myanmar, NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index 8fadd7cdb..979206711 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -39,6 +39,8 @@ #define complex_var_u8_1() var2.u8[3] +#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32 + enum hb_ot_shape_zero_width_marks_type_t { HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, @@ -154,6 +156,16 @@ struct hb_ot_complex_shaper_t */ bool (*disable_otl) (const hb_ot_shape_plan_t *plan); + /* reorder_marks() + * Called during shape(). + * Shapers can use to modify ordering of combining marks. + * May be NULL. + */ + void (*reorder_marks) (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, + unsigned int end); + hb_ot_shape_zero_width_marks_type_t zero_width_marks; bool fallback_position; diff --git a/src/hb-ot-shape-complex-thai.cc b/src/hb-ot-shape-complex-thai.cc index 924247f17..651c47f8f 100644 --- a/src/hb-ot-shape-complex-thai.cc +++ b/src/hb-ot-shape-complex-thai.cc @@ -378,6 +378,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = NULL, /* compose */ NULL, /* setup_masks */ NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-tibetan.cc b/src/hb-ot-shape-complex-tibetan.cc index aadf59f5a..a85ac0f4b 100644 --- a/src/hb-ot-shape-complex-tibetan.cc +++ b/src/hb-ot-shape-complex-tibetan.cc @@ -58,6 +58,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = NULL, /* compose */ NULL, /* setup_masks */ NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index a5ab0ab2a..ac3a24867 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -607,6 +607,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = compose_use, setup_masks_use, NULL, /* disable_otl */ + NULL, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index a5144888a..fd9e7c2a8 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -345,14 +345,18 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) break; - /* We are going to do a O(n^2). Only do this if the sequence is short. */ - if (end - i > 10) { + /* We are going to do a O(n^2). Only do this if the sequence is short, + * but not too short ;). */ + if (end - i < 2 || end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { i = end; continue; } buffer->sort (i, end, compare_combining_class); + if (plan->shaper->reorder_marks) + plan->shaper->reorder_marks (plan, buffer, i, end); + i = end; } diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index d29800c45..ecb836db9 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -44,6 +44,7 @@ TESTS = \ tests/arabic-fallback-shaping.tests \ tests/arabic-feature-order.tests \ tests/arabic-like-joining.tests \ + tests/arabic-mark-order.tests \ tests/automatic-fractions.tests \ tests/cluster.tests \ tests/color-fonts.tests \ diff --git a/test/shaping/fonts/sha1sum/24b8d24d00ae86f49791b746da4c9d3f717a51a8.ttf b/test/shaping/fonts/sha1sum/24b8d24d00ae86f49791b746da4c9d3f717a51a8.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dc290adb57a0e1b5257627efd6bd063dab069a4d GIT binary patch literal 7160 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 Gi2fI?Hfm@9 literal 0 HcmV?d00001 diff --git a/test/shaping/fonts/sha1sum/94a5d6fb15a27521fba9ea4aee9cb39b2d03322a.ttf b/test/shaping/fonts/sha1sum/94a5d6fb15a27521fba9ea4aee9cb39b2d03322a.ttf new file mode 100644 index 0000000000000000000000000000000000000000..baf544f63b66f7373734eebbf6bba36dfb2fff5e GIT binary patch literal 6816 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 Date: Wed, 4 Oct 2017 15:06:48 +0200 Subject: [PATCH 0429/1326] Improve performance of ligature component matching This O(N^2) was introduced in 8b2c94c43fd335b944d5e5487265706b8e0f9041. Make it O(N). --- src/hb-ot-layout-gsubgpos-private.hh | 37 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index aa0862ad2..cedf96e3f 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -764,6 +764,12 @@ static inline bool match_input (hb_apply_context_t *c, unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); + enum { + LIGBASE_NOT_CHECKED, + LIGBASE_MAY_NOT_SKIP, + LIGBASE_MAY_SKIP + } ligbase = LIGBASE_NOT_CHECKED; + match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { @@ -783,29 +789,34 @@ static inline bool match_input (hb_apply_context_t *c, { /* ...unless, we are attached to a base ligature and that base * ligature is ignorable. */ - bool found = false; - const hb_glyph_info_t *out = buffer->out_info; - unsigned int j = buffer->out_len; - while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) + if (ligbase == LIGBASE_NOT_CHECKED) { - if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0) + bool found = false; + const hb_glyph_info_t *out = buffer->out_info; + unsigned int j = buffer->out_len; + while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) { + if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0) + { + j--; + found = true; + break; + } j--; - found = true; - break; } - j--; + + if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES) + ligbase = LIGBASE_MAY_SKIP; + else + ligbase = LIGBASE_MAY_NOT_SKIP; } - if (!found) - return_trace (false); - - if (skippy_iter.may_skip (c, out[j]) != hb_apply_context_t::matcher_t::SKIP_YES) + if (ligbase == LIGBASE_MAY_NOT_SKIP) return_trace (false); } } else - { + { /* If first component was NOT attached to a previous ligature component, * all subsequent components should also NOT be attached to any ligature * component, unless they are attached to the first component itself! */ From c9e2cf6f55c7682b8e7020654945ddd074ebfd24 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 4 Oct 2017 16:59:22 +0200 Subject: [PATCH 0430/1326] [ot] Remove 'mal' and 'gle' lang tags Fixes https://github.com/behdad/harfbuzz/issues/477 --- src/hb-ot-tag.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hb-ot-tag.cc b/src/hb-ot-tag.cc index f3671babe..59b7d6a6d 100644 --- a/src/hb-ot-tag.cc +++ b/src/hb-ot-tag.cc @@ -394,7 +394,6 @@ static const LangTag ot_languages[] = { {"gkp", HB_TAG('G','K','P',' ')}, /* Kpelle (Guinea) */ {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ - {"gle", HB_TAG('I','R','T',' ')}, /* Irish Traditional */ {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ {"gnn", HB_TAG('G','N','N',' ')}, /* Gumatj */ @@ -552,7 +551,6 @@ static const LangTag ot_languages[] = { {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ - {"mal", HB_TAG('M','A','L',' ')}, /* Malayalam */ {"mam", HB_TAG('M','A','M',' ')}, /* Mam */ {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ From 48a9406839f086735a05a2f1a07987b8a6bd6d33 Mon Sep 17 00:00:00 2001 From: fanc999 Date: Sat, 7 Oct 2017 18:57:14 +0800 Subject: [PATCH 0431/1326] Fix build of HarfBuzz tools and HarfBuzz-GObject on Visual Studio (#555) * hb-buffer.h: Mark hb_buffer_diff() for export This will fix the tools builds on Visual Studio, as the symbol is used by the tools. * build: Adapt NMake Makefiles for GLib 2.53.4 or later glib-mkenums was ported from a PERL script to a Python script, so we need to update how we generate the enum sources for HarfBuzz-GObject in the NMake builds. Let this be known in the build documentation for MSVC builds. One of the problems with the underlying cmd.exe that the NMake Makefiles run on is that shebang lines are not recognized, so we need to to test run the script with Python and see whether it succeeded by outputing a source file that is larger than 0 in file size (since running the PERL version of the script will clearly fail and cause an empty file to be created). If it succeeds, we then run a small Python utility script that makes the necessary string replacements, and we are done. If that fails, then we run the glib-mkenums script with PERL, and do the replacements with the PERL one-liners as we did before. We need to make replace.py use latin-1 encoding when using Python 3.x to cope with the copyright sign that is in the generated enum sources. --- src/hb-buffer.h | 2 +- win32/Makefile.am | 4 +++- win32/README.txt | 5 +++-- win32/generate-msvc.mak | 17 ++++++++++++----- win32/info-msvc.mak | 5 ++++- win32/replace.py | 2 +- win32/sed-enums-srcs.py | 36 ++++++++++++++++++++++++++++++++++++ 7 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 win32/sed-enums-srcs.py diff --git a/src/hb-buffer.h b/src/hb-buffer.h index 1d633f7dc..42564bb19 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -504,7 +504,7 @@ typedef enum { /*< flags >*/ } hb_buffer_diff_flags_t; /* Compare the contents of two buffers, report types of differences. */ -hb_buffer_diff_flags_t +HB_EXTERN hb_buffer_diff_flags_t hb_buffer_diff (hb_buffer_t *buffer, hb_buffer_t *reference, hb_codepoint_t dottedcircle_glyph, diff --git a/win32/Makefile.am b/win32/Makefile.am index 63ba4680c..79ce999da 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -11,6 +11,8 @@ EXTRA_DIST = \ install.mak \ introspection-msvc.mak \ Makefile.vc \ - README.txt + README.txt \ + replace.py \ + sed-enums-srcs.py -include $(top_srcdir)/git.mk diff --git a/win32/README.txt b/win32/README.txt index 90554c012..185a44c3e 100644 --- a/win32/README.txt +++ b/win32/README.txt @@ -57,8 +57,9 @@ GLIB: Enable GLib support in HarfBuzz, which also uses the GLib unicode GOBJECT: Enable building the HarfBuzz-GObject DLL, and thus implies GLib support. This requires the GObject libraries and glib-mkenums script, - along with PERL to generate the enum sources and headers, which is - required for the build. + along with Python (when using GObject/GLib 2.53.4 or later) or PERL + (when using GObject/GLib 2.53.3 or earlier) to generate the enum + sources and headers, which is required for the build. INTROSPECTION: Enable build of introspection files, for making HarfBuzz bindings for other programming languages available, such as diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak index b0727d507..0d5c4b062 100644 --- a/win32/generate-msvc.mak +++ b/win32/generate-msvc.mak @@ -12,13 +12,20 @@ config.h: config.h.win32 # we are already using PERL, use PERL one-liners. !if "$(GOBJECT)" == "1" $(HB_GOBJECT_ENUM_GENERATED_SOURCES): ..\src\hb-gobject-enums.h.tmpl ..\src\hb-gobject-enums.cc.tmpl $(HB_ACTUAL_HEADERS) + -$(PYTHON) $(PREFIX)\bin\glib-mkenums \ + --identifier-prefix hb_ --symbol-prefix hb_gobject \ + --template ..\src\$(@F).tmpl $(HB_ACTUAL_HEADERS) > $@.tmp + for %%f in ($@.tmp) do if %%~zf gtr 0 $(PYTHON) sed-enums-srcs.py --input=$@.tmp --output=$@ + @-del $@.tmp + if not exist $@ \ $(PERL) $(PREFIX)\bin\glib-mkenums \ --identifier-prefix hb_ --symbol-prefix hb_gobject \ - --template ..\src\$(@F).tmpl $(HB_ACTUAL_HEADERS) > $@ - $(PERL) -p -i.tmp1 -e "s/_t_get_type/_get_type/g" $@ - $(PERL) -p -i.tmp2 -e "s/_T \(/ (/g" $@ - @-del $@.tmp1 - @-del $@.tmp2 + --template ..\src\$(@F).tmpl $(HB_ACTUAL_HEADERS) > $@.tmp + if exist $@.tmp $(PERL) -p -i.tmp1 -e "s/_t_get_type/_get_type/g" $@.tmp + if exist $@.tmp $(PERL) -p -i.tmp2 -e "s/_T \(/ (/g" $@.tmp + @if exist $@.tmp.tmp1 del $@.tmp.tmp1 + @if exist $@.tmp.tmp2 del $@.tmp.tmp2 + @if exist $@.tmp move $@.tmp $@ !endif # Create the build directories diff --git a/win32/info-msvc.mak b/win32/info-msvc.mak index 4586548ce..2a61b180c 100644 --- a/win32/info-msvc.mak +++ b/win32/info-msvc.mak @@ -107,7 +107,10 @@ help: @echo GOBJECT: @echo Enable the HarfBuzz-GObject library, also implies GLib2 support, @echo requires the GNOME GLib2 libraries and tools, notably the glib-mkenums - @echo tool script, which will require a PERL interpreter (use + @echo tool script, which will require a Python interpretor (when using + @echo GObject/GLib 2.53.4 or later; use PYTHON=^$(PATH_TO_PYTHON_INTERPRETOR) + @echo if the Python interpretor is not already in your PATH) or PERL + @echo interpreter (when using GObject/GLib 2.53.3 or earlier; use @echo PERL=^$(PATH_TO_PERL_INTERPRETOR)) if it is not already in your PATH). @echo. @echo GRAPHITE2: diff --git a/win32/replace.py b/win32/replace.py index 3aeceb1f7..e3ef16351 100644 --- a/win32/replace.py +++ b/win32/replace.py @@ -25,7 +25,7 @@ def open_file(filename, mode): if sys.version_info[0] < 3: return open(filename, mode=mode) else: - return open(filename, mode=mode, encoding='utf-8') + return open(filename, mode=mode, encoding='latin-1') def replace_multi(src, dest, replace_items): with open_file(src, 'r') as s: diff --git a/win32/sed-enums-srcs.py b/win32/sed-enums-srcs.py new file mode 100644 index 000000000..ee7614895 --- /dev/null +++ b/win32/sed-enums-srcs.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# +# Utility script to replace strings in the +# generated enum sources, as needed by the build + +# Author: Fan, Chun-wei +# Date: Oct. 5, 2017 + +import os +import sys +import argparse + +from replace import replace_multi + +def main(argv): + parser = argparse.ArgumentParser(description='Replace strings in generated enum sources') + parser.add_argument('--input', help='input generated temporary enum source', + required=True) + parser.add_argument('--output', + help='output generated final enum source', required=True) + args = parser.parse_args() + + # check whether the generated temporary enum source exists + if not os.path.exists(args.input): + raise SystemExit('Specified generated temporary enum source \'%s\' is invalid' % args.input) + + replace_items = {'_t_get_type': '_get_type', + '_T (': ' ('} + + # Generate the final enum source + replace_multi(args.input, + args.output, + replace_items) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) \ No newline at end of file From c2545b921523538e8237ff6a2591f6cb75ee79f1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 7 Oct 2017 12:56:53 +0200 Subject: [PATCH 0432/1326] Add check for HB_EXTERNs https://github.com/behdad/harfbuzz/pull/555 --- src/Makefile.am | 1 + src/check-externs.sh | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100755 src/check-externs.sh diff --git a/src/Makefile.am b/src/Makefile.am index 0c077d990..ea550d266 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -300,6 +300,7 @@ check: harfbuzz.def # For check-defs.sh dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ check-defs.sh \ + check-externs.sh \ check-header-guards.sh \ check-includes.sh \ check-libstdc++.sh \ diff --git a/src/check-externs.sh b/src/check-externs.sh new file mode 100755 index 000000000..63cc7d5bb --- /dev/null +++ b/src/check-externs.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +LC_ALL=C +export LC_ALL + +test -z "$srcdir" && srcdir=. +stat=0 + +test "x$HBHEADERS" = x && HBHEADERS=`cd "$srcdir"; find . -maxdepth 1 -name 'hb*.h'` +test "x$EGREP" = x && EGREP='grep -E' + + +echo 'Checking that all public symbols are exported with HB_EXTERN' + +for x in $HBHEADERS; do + test -f "$srcdir/$x" && x="$srcdir/$x" + $EGREP -B1 '^hb_' "$x" | $EGREP -E -v '^(--|hb_|HB_EXTERN )' -A1 +done | +grep . >&2 && stat=1 + +exit $stat From 5f50f8837f918ca1d176355d1538e0e6c9703f41 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 7 Oct 2017 13:17:33 +0200 Subject: [PATCH 0433/1326] [arabic] Fix cluster merging --- src/hb-ot-shape-complex-arabic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 28dd4e1fe..f74196112 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -676,7 +676,7 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan, DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d\n", cc, i, j); hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS]; assert (j - i <= ARRAY_LENGTH (temp)); - buffer->merge_out_clusters (start, j); + buffer->merge_clusters (start, j); memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t)); memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t)); memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t)); From 3f9370d9e5051b1abf2fc94be2e10a39c8069f75 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 11:34:53 +0200 Subject: [PATCH 0434/1326] Fix TODO item --- src/hb-font.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index a684c234d..50da49e74 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1158,7 +1158,18 @@ hb_font_create_sub_font (hb_font_t *parent) font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; - /* TODO: copy variation coordinates. */ + font->num_coords = parent->num_coords; + if (!font->num_coords) + font->coords = NULL; + else + { + unsigned int size = parent->num_coords * sizeof (parent->coords[0]); + font->coords = (int *) malloc (size); + if (unlikely (!font->coords)) + font->num_coords = 0; + else + memcpy (font->coords, parent->coords, size); + } return font; } From b57f18da700837a57df9606290160ea6e96accc8 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 11:47:47 +0200 Subject: [PATCH 0435/1326] Add hb_font_[sg]et_ptem() to set/get point size on font New API: hb_font_set_ptem() hb_font_get_ptem() Needed for hb-coretext optical sizing: https://github.com/behdad/harfbuzz/issues/360 --- docs/harfbuzz-sections.txt | 2 ++ src/hb-font-private.hh | 5 ++++- src/hb-font.cc | 41 ++++++++++++++++++++++++++++++++++++++ src/hb-font.h | 10 ++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 6ceefd250..6d86d9418 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -246,6 +246,7 @@ hb_font_get_nominal_glyph hb_font_get_nominal_glyph_func_t hb_font_get_parent hb_font_get_ppem +hb_font_get_ptem hb_font_get_scale hb_font_get_user_data hb_font_get_variation_glyph @@ -261,6 +262,7 @@ hb_font_set_funcs hb_font_set_funcs_data hb_font_set_parent hb_font_set_ppem +hb_font_set_ptem hb_font_set_scale hb_font_set_user_data hb_variation_t diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index ed9f2c54a..30661c322 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -108,6 +108,8 @@ struct hb_font_t { unsigned int x_ppem; unsigned int y_ppem; + float ptem; + /* Font variation coordinates. */ unsigned int num_coords; int *coords; @@ -123,7 +125,8 @@ struct hb_font_t { DIRTY_FUNCS = 0x0004, DIRTY_SCALE = 0x0008, DIRTY_PPEM = 0x0010, - DIRTY_VARIATIONS = 0x0020, + DIRTY_PTEM = 0x0020, + DIRTY_VARIATIONS = 0x0040, } dirty; struct hb_shaper_data_t shaper_data; diff --git a/src/hb-font.cc b/src/hb-font.cc index 50da49e74..c47e2c14a 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1157,6 +1157,7 @@ hb_font_create_sub_font (hb_font_t *parent) font->y_scale = parent->y_scale; font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; + font->ptem = parent->ptem; font->num_coords = parent->num_coords; if (!font->num_coords) @@ -1199,6 +1200,7 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ + -1, /* ptem */ 0, /* num_coords */ NULL, /* coords */ @@ -1597,6 +1599,45 @@ hb_font_get_ppem (hb_font_t *font, if (y_ppem) *y_ppem = font->y_ppem; } +/** + * hb_font_set_ptem: + * @font: a font. + * @ptem: + * + * Sets "point size" of the font. + * + * Since: 1.6.0 + **/ +void +hb_font_set_ptem (hb_font_t *font, float ptem) +{ + if (font->immutable) + return; + + if (font->ptem == ptem) + return; + + font->dirty |= font->DIRTY_PTEM; + + font->ptem = ptem; +} + +/** + * hb_font_get_ptem: + * @font: a font. + * + * Gets the "point size" of the font. A value of -1 means unset. + * + * Return value: Point size. + * + * Since: 0.9.2 + **/ +float +hb_font_get_ptem (hb_font_t *font) +{ + return font->ptem; +} + /* * Variations */ diff --git a/src/hb-font.h b/src/hb-font.h index 85fb56d5b..8fb1849de 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -607,6 +607,16 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, unsigned int *y_ppem); +/* + * Point size per EM. Used for optical-sizing in CoreText. + * A -1 means "not set". + */ +HB_EXTERN void +hb_font_set_ptem (hb_font_t *font, float ptem); + +HB_EXTERN float +hb_font_get_ptem (hb_font_t *font); + HB_EXTERN void hb_font_set_variations (hb_font_t *font, const hb_variation_t *variations, From c0c2dbc871667c32ac8eedb11de64078ef24a429 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 12:23:35 +0200 Subject: [PATCH 0436/1326] Remove dirty tracking Turns out I don't need this to resolve CoreText optical sizing issue after all. https://github.com/behdad/harfbuzz/issues/360 --- src/hb-face-private.hh | 9 --------- src/hb-face.cc | 17 ----------------- src/hb-font-private.hh | 13 ------------- src/hb-font.cc | 39 --------------------------------------- 4 files changed, 78 deletions(-) diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh index 72f08a599..43e7b1cb3 100644 --- a/src/hb-face-private.hh +++ b/src/hb-face-private.hh @@ -54,13 +54,6 @@ struct hb_face_t { mutable unsigned int upem; /* Units-per-EM. */ mutable unsigned int num_glyphs; /* Number of glyphs. */ - enum dirty_t { - DIRTY_NOTHING = 0x0000, - DIRTY_INDEX = 0x0001, - DIRTY_UPEM = 0x0002, - DIRTY_NUM_GLYPHS = 0x0004, - } dirty; - struct hb_shaper_data_t shaper_data; /* Various shaper data. */ /* Various non-shaping data. */ @@ -106,8 +99,6 @@ struct hb_face_t { HB_INTERNAL void load_num_glyphs (void) const; }; -HB_MARK_AS_FLAG_T (hb_face_t::dirty_t); - extern HB_INTERNAL const hb_face_t _hb_face_nil; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/src/hb-face.cc b/src/hb-face.cc index 22998f005..d7d736d7b 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -51,8 +51,6 @@ const hb_face_t _hb_face_nil = { 1000, /* upem */ 0, /* num_glyphs */ - hb_face_t::DIRTY_NOTHING, /* dirty */ - { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -367,11 +365,6 @@ hb_face_set_index (hb_face_t *face, if (face->immutable) return; - if (face->index == index) - return; - - face->dirty |= face->DIRTY_INDEX; - face->index = index; } @@ -407,11 +400,6 @@ hb_face_set_upem (hb_face_t *face, if (face->immutable) return; - if (face->upem == upem) - return; - - face->dirty |= face->DIRTY_UPEM; - face->upem = upem; } @@ -456,11 +444,6 @@ hb_face_set_glyph_count (hb_face_t *face, if (face->immutable) return; - if (face->num_glyphs == glyph_count) - return; - - face->dirty |= face->DIRTY_NUM_GLYPHS; - face->num_glyphs = glyph_count; } diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 30661c322..d2801fb86 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -118,17 +118,6 @@ struct hb_font_t { void *user_data; hb_destroy_func_t destroy; - enum dirty_t { - DIRTY_NOTHING = 0x0000, - DIRTY_FACE = 0x0001, - DIRTY_PARENT = 0x0002, - DIRTY_FUNCS = 0x0004, - DIRTY_SCALE = 0x0008, - DIRTY_PPEM = 0x0010, - DIRTY_PTEM = 0x0020, - DIRTY_VARIATIONS = 0x0040, - } dirty; - struct hb_shaper_data_t shaper_data; @@ -556,8 +545,6 @@ struct hb_font_t { } }; -HB_MARK_AS_FLAG_T (hb_font_t::dirty_t); - #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); #include "hb-shaper-list.hh" diff --git a/src/hb-font.cc b/src/hb-font.cc index c47e2c14a..888420792 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1209,8 +1209,6 @@ hb_font_get_empty (void) NULL, /* user_data */ NULL, /* destroy */ - hb_font_t::DIRTY_NOTHING, /* dirty */ - { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -1363,11 +1361,6 @@ hb_font_set_parent (hb_font_t *font, if (!parent) parent = hb_font_get_empty (); - if (parent == font->parent) - return; - - font->dirty |= font->DIRTY_PARENT; - hb_font_t *old = font->parent; font->parent = hb_font_reference (parent); @@ -1410,11 +1403,6 @@ hb_font_set_face (hb_font_t *font, if (unlikely (!face)) face = hb_face_get_empty (); - if (font->face == face) - return; - - font->dirty |= font->DIRTY_FACE; - hb_face_t *old = font->face; font->face = hb_face_reference (face); @@ -1468,8 +1456,6 @@ hb_font_set_funcs (hb_font_t *font, if (!klass) klass = hb_font_funcs_get_empty (); - font->dirty |= font->DIRTY_FUNCS; - hb_font_funcs_reference (klass); hb_font_funcs_destroy (font->klass); font->klass = klass; @@ -1525,11 +1511,6 @@ hb_font_set_scale (hb_font_t *font, if (font->immutable) return; - if (font->x_scale == x_scale && font->y_scale == y_scale) - return; - - font->dirty |= font->DIRTY_SCALE; - font->x_scale = x_scale; font->y_scale = y_scale; } @@ -1571,11 +1552,6 @@ hb_font_set_ppem (hb_font_t *font, if (font->immutable) return; - if (font->x_ppem == x_ppem && font->y_ppem == y_ppem) - return; - - font->dirty |= font->DIRTY_PPEM; - font->x_ppem = x_ppem; font->y_ppem = y_ppem; } @@ -1614,11 +1590,6 @@ hb_font_set_ptem (hb_font_t *font, float ptem) if (font->immutable) return; - if (font->ptem == ptem) - return; - - font->dirty |= font->DIRTY_PTEM; - font->ptem = ptem; } @@ -1647,16 +1618,6 @@ _hb_font_adopt_var_coords_normalized (hb_font_t *font, int *coords, /* 2.14 normalized */ unsigned int coords_length) { - if (font->num_coords == coords_length && - (coords_length == 0 || - 0 == memcmp (font->coords, coords, coords_length * sizeof (coords[0])))) - { - free (coords); - return; - } - - font->dirty |= font->DIRTY_VARIATIONS; - free (font->coords); font->coords = coords; From 16d02a58cf187dbcecc1c796acdc5d3a70ca288e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 12:28:06 +0200 Subject: [PATCH 0437/1326] [coretext] Change default font size from 36 to 18 --- src/hb-coretext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index ba96d3994..5c0b65af0 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -229,7 +229,7 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) * Since we always create CTFont at a fixed size, our CTFont lives in face_data * instead of font_data. Which is good, because when people change scale on * hb_font_t, we won't need to update our CTFont. */ - data->ct_font = create_ct_font (data->cg_font, 36.); + data->ct_font = create_ct_font (data->cg_font, 18.); if (unlikely (!data->ct_font)) { DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); From 8d450dd188dea2d63a03f74d903a76741de8a217 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 12:43:46 +0200 Subject: [PATCH 0438/1326] Infrastructure for creating CTFont with correct font size https://github.com/behdad/harfbuzz/issues/360 --- src/hb-shaper-private.hh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hb-shaper-private.hh b/src/hb-shaper-private.hh index 381398a61..2481ef8ac 100644 --- a/src/hb-shaper-private.hh +++ b/src/hb-shaper-private.hh @@ -88,11 +88,23 @@ struct hb_shaper_data_t { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); #define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \ + HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true) + +#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \ bool \ HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \ {\ retry: \ HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \ + if (likely (data) && !(condition)) { \ + /* Drop and recreate. */ \ + /* If someone dropped it in the mean time, throw it away and don't touch it. \ + * Otherwise, destruct it. */ \ + if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, NULL)) { \ + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \ + } \ + goto retry; \ + } \ if (unlikely (!data)) { \ data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \ if (unlikely (!data)) \ From f9b4c6570a4725eec5393f86e6468a189ac8c6be Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 12:51:25 +0200 Subject: [PATCH 0439/1326] [coretext] Move font size to a macro --- src/hb-coretext.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 5c0b65af0..10859e161 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -36,6 +36,7 @@ #define HB_DEBUG_CORETEXT (HB_DEBUG+0) #endif +#define HB_CORETEXT_FONT_SIZE 18.0 static void release_table_data (void *user_data) @@ -229,7 +230,7 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) * Since we always create CTFont at a fixed size, our CTFont lives in face_data * instead of font_data. Which is good, because when people change scale on * hb_font_t, we won't need to update our CTFont. */ - data->ct_font = create_ct_font (data->cg_font, 18.); + data->ct_font = create_ct_font (data->cg_font, HB_CORETEXT_FONT_SIZE); if (unlikely (!data->ct_font)) { DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); From a8e466c3c12a3499028cb576721e5f85ff4cbf2d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 13:05:59 +0200 Subject: [PATCH 0440/1326] [coretext] Move CT_Font to font data Towards implementing optical sizing. Untested; won't compile. https://github.com/behdad/harfbuzz/issues/360 --- src/hb-coretext.cc | 85 ++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 10859e161..3f1c67113 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -203,51 +203,26 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) return ct_font; } -struct hb_coretext_shaper_face_data_t { - CGFontRef cg_font; - CTFontRef ct_font; -}; +typedef CGFontRef hb_coretext_shaper_face_data_t; hb_coretext_shaper_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { - hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); - if (unlikely (!data)) - return NULL; + hb_coretext_shaper_face_data_t *cg_font = create_cg_font (face); - data->cg_font = create_cg_font (face); - if (unlikely (!data->cg_font)) + if (unlikely (!cg_font)) { DEBUG_MSG (CORETEXT, face, "CGFont creation failed.."); - free (data); return NULL; } - /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table, - * which can make the font too tight at large sizes. 36pt should be a good semi-neutral - * size. - * - * Since we always create CTFont at a fixed size, our CTFont lives in face_data - * instead of font_data. Which is good, because when people change scale on - * hb_font_t, we won't need to update our CTFont. */ - data->ct_font = create_ct_font (data->cg_font, HB_CORETEXT_FONT_SIZE); - if (unlikely (!data->ct_font)) - { - DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); - CFRelease (data->cg_font); - free (data); - return NULL; - } - - return data; + return cg_font; } void -_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) +_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *cg_font) { - CFRelease (data->ct_font); - CFRelease (data->cg_font); - free (data); + CFRelease (cg_font); } /* @@ -257,8 +232,8 @@ CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->cg_font; + hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); + return cg_font; } @@ -266,17 +241,31 @@ hb_coretext_face_get_cg_font (hb_face_t *face) * shaper font data */ -struct hb_coretext_shaper_font_data_t {}; +typedef CTFontRef hb_coretext_shaper_font_data_t; hb_coretext_shaper_font_data_t * -_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED) +_hb_coretext_shaper_font_data_create (hb_font_t *font) { - return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; + hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); + + float ptem = font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; + + hb_coretext_shaper_font_data_t *ct_font = create_ct_font (cg_font, ptem); + + if (unlikely (!ct_font)) + { + DEBUG_MSG (CORETEXT, font, "CGFont creation failed.."); + return NULL; + } + + return ct_font; } void -_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) +_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *ct_font) { + CFRelease (ct_font); } @@ -304,10 +293,9 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { - hb_face_t *face = font->face; - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->ct_font; + if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; + hb_coretext_shaper_font_data_t *ct_font = HB_SHAPER_DATA_GET (font); + return ct_font; } @@ -539,9 +527,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, unsigned int num_features) { hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); + hb_coretext_shaper_font_data_t *ct_font = HB_SHAPER_DATA_GET (font); - CGFloat ct_font_size = CTFontGetSize (face_data->ct_font); + CGFloat ct_font_size = CTFontGetSize (ct_font); CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; @@ -676,7 +665,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); CFRelease (attributes); - range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc); + range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, font_desc); CFRelease (font_desc); } else @@ -830,7 +819,7 @@ resize_and_retry: CFRelease (lang); } CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), - kCTFontAttributeName, face_data->ct_font); + kCTFontAttributeName, ct_font); if (num_features && range_records.len) { @@ -948,7 +937,7 @@ resize_and_retry: */ CFDictionaryRef attributes = CTRunGetAttributes (run); CTFontRef run_ct_font = static_cast(CFDictionaryGetValue (attributes, kCTFontAttributeName)); - if (!CFEqual (run_ct_font, face_data->ct_font)) + if (!CFEqual (run_ct_font, ct_font)) { /* The run doesn't use our main font instance. We have to figure out * whether font fallback happened, or this is just CoreText giving us @@ -986,13 +975,13 @@ resize_and_retry: CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); if (run_cg_font) { - matched = CFEqual (run_cg_font, face_data->cg_font); + matched = CFEqual (run_cg_font, cg_font); CFRelease (run_cg_font); } } if (!matched) { - CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey); + CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey); CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey); CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0); CFRelease (run_ps_name); From f33413075655e6383cd16bc31f0bf804dcec1c64 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 13:17:46 +0200 Subject: [PATCH 0441/1326] [coretext] Another try --- src/hb-coretext.cc | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 3f1c67113..26cc07c9e 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -203,12 +203,10 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) return ct_font; } -typedef CGFontRef hb_coretext_shaper_face_data_t; - hb_coretext_shaper_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { - hb_coretext_shaper_face_data_t *cg_font = create_cg_font (face); + CGFontRef cg_font = create_cg_font (face); if (unlikely (!cg_font)) { @@ -216,13 +214,13 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) return NULL; } - return cg_font; + return (hb_coretext_shaper_face_data_t *) cg_font; } void -_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *cg_font) +_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) { - CFRelease (cg_font); + CFRelease ((CGFontRef) data); } /* @@ -232,8 +230,7 @@ CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); - return cg_font; + return (CGFontRef) HB_SHAPER_DATA_GET (face); } @@ -241,17 +238,15 @@ hb_coretext_face_get_cg_font (hb_face_t *face) * shaper font data */ -typedef CTFontRef hb_coretext_shaper_font_data_t; - hb_coretext_shaper_font_data_t * _hb_coretext_shaper_font_data_create (hb_font_t *font) { if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; - hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); float ptem = font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; - hb_coretext_shaper_font_data_t *ct_font = create_ct_font (cg_font, ptem); + CTFontRef ct_font = create_ct_font (cg_font, ptem); if (unlikely (!ct_font)) { @@ -259,13 +254,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) return NULL; } - return ct_font; + return (hb_coretext_shaper_font_data_t *) ct_font; } void -_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *ct_font) +_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) { - CFRelease (ct_font); + CFRelease ((CTFontRef) data); } @@ -294,8 +289,7 @@ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; - hb_coretext_shaper_font_data_t *ct_font = HB_SHAPER_DATA_GET (font); - return ct_font; + return (CTFontRef)_SHAPER_DATA_GET (font); } @@ -527,8 +521,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, unsigned int num_features) { hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *cg_font = HB_SHAPER_DATA_GET (face); - hb_coretext_shaper_font_data_t *ct_font = HB_SHAPER_DATA_GET (font); + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font); CGFloat ct_font_size = CTFontGetSize (ct_font); CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; From db7a73ce0781d1fec0235e419ac448565dcfc8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Wed, 11 Oct 2017 13:24:39 +0200 Subject: [PATCH 0442/1326] [coretext] Fix build --- src/hb-coretext.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 26cc07c9e..9b680abf6 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -241,7 +241,8 @@ hb_coretext_face_get_cg_font (hb_face_t *face) hb_coretext_shaper_font_data_t * _hb_coretext_shaper_font_data_create (hb_font_t *font) { - if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; + hb_face_t *face = font->face; + if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); float ptem = font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; @@ -289,7 +290,7 @@ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; - return (CTFontRef)_SHAPER_DATA_GET (font); + return (CTFontRef)HB_SHAPER_DATA_GET (font); } From a5ebe1d4aec41bc5e289a7969e5e5f7bb57733b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Wed, 11 Oct 2017 13:32:38 +0200 Subject: [PATCH 0443/1326] [coretext] Recreate CTFont if pt size changed Attempt at fixing #360 --- src/hb-coretext.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 9b680abf6..8219284dc 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -71,8 +71,9 @@ hb_coretext_face_create (CGFontRef cg_font) HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) -HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font) - +HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, + abs (CTFontGetSize((CTFontRef) data) - + (font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem)) < 1) /* * shaper face data From 296d0134c9d04c82cc0bffd545b0fd9a308a2530 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 14:09:30 +0200 Subject: [PATCH 0444/1326] [coretext] Change default point size to 12 --- src/hb-coretext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 8219284dc..432e0cc12 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -36,7 +36,7 @@ #define HB_DEBUG_CORETEXT (HB_DEBUG+0) #endif -#define HB_CORETEXT_FONT_SIZE 18.0 +#define HB_CORETEXT_FONT_SIZE 12.0 static void release_table_data (void *user_data) From 84686bf4c75c001e7cfb2eabdf391b2e76cae335 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:02:48 +0200 Subject: [PATCH 0445/1326] [coretext-aat] Also pass through CoreText if font has kerx table SFNSText has kerx table which apparently is applied. --- src/hb-coretext.cc | 28 +++++++++++++--------------- src/hb-coretext.h | 1 + 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 432e0cc12..f43abb9f5 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -1249,22 +1249,20 @@ struct hb_coretext_aat_shaper_face_data_t {}; hb_coretext_aat_shaper_face_data_t * _hb_coretext_aat_shaper_face_data_create (hb_face_t *face) { - hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT); - /* Umm, we just reference the table to check whether it exists. - * Maybe add better API for this? */ - if (!hb_blob_get_length (mort_blob)) - { - hb_blob_destroy (mort_blob); - mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX); - if (!hb_blob_get_length (mort_blob)) - { - hb_blob_destroy (mort_blob); - return NULL; - } - } - hb_blob_destroy (mort_blob); + static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX}; - return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; + for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++) + { + hb_blob_t *blob = face->reference_table (tags[i]); + if (hb_blob_get_length (blob)) + { + hb_blob_destroy (blob); + return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; + } + hb_blob_destroy (blob); + } + + return NULL; } void diff --git a/src/hb-coretext.h b/src/hb-coretext.h index 82066e4e0..c9136ff4c 100644 --- a/src/hb-coretext.h +++ b/src/hb-coretext.h @@ -42,6 +42,7 @@ HB_BEGIN_DECLS #define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t') #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') +#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x') HB_EXTERN hb_face_t * From 269cf1ca82c34c6f6ea126e7333743e5c381453b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:24:22 +0200 Subject: [PATCH 0446/1326] Correctly initialize ptem --- src/hb-font.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-font.cc b/src/hb-font.cc index 888420792..a43656d9d 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1124,6 +1124,7 @@ hb_font_create (hb_face_t *face) font->parent = hb_font_get_empty (); font->face = hb_face_reference (face); font->klass = hb_font_funcs_get_empty (); + font->ptem = -1; font->x_scale = font->y_scale = hb_face_get_upem (face); From a4b46212c5e76494cfde5af6f299e08902aff0d5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:29:22 +0200 Subject: [PATCH 0447/1326] [coretext] Adjust font size check for 0 --- src/hb-coretext.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index f43abb9f5..8cfec1e32 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -73,7 +73,7 @@ hb_coretext_face_create (CGFontRef cg_font) HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, abs (CTFontGetSize((CTFontRef) data) - - (font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem)) < 1) + (font->ptem <= 0 ? HB_CORETEXT_FONT_SIZE : font->ptem)) < 1) /* * shaper face data @@ -246,7 +246,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); - float ptem = font->ptem < 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; + float ptem = font->ptem <= 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; CTFontRef ct_font = create_ct_font (cg_font, ptem); From 06c14225b20aa43ae88d362be2de577f6cf3f7b9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:29:53 +0200 Subject: [PATCH 0448/1326] [coretext] Minor --- src/hb-coretext.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 8cfec1e32..a2bbfbd1f 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -36,6 +36,7 @@ #define HB_DEBUG_CORETEXT (HB_DEBUG+0) #endif +/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ #define HB_CORETEXT_FONT_SIZE 12.0 static void From 374bb48d902025e8b8d8acbe525ff43540daee36 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:37:50 +0200 Subject: [PATCH 0449/1326] Change ptem API to make 0 mean unset --- src/hb-font.cc | 5 ++--- src/hb-font.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hb-font.cc b/src/hb-font.cc index a43656d9d..5673e66e3 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1124,7 +1124,6 @@ hb_font_create (hb_face_t *face) font->parent = hb_font_get_empty (); font->face = hb_face_reference (face); font->klass = hb_font_funcs_get_empty (); - font->ptem = -1; font->x_scale = font->y_scale = hb_face_get_upem (face); @@ -1201,7 +1200,7 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ - -1, /* ptem */ + 0, /* ptem */ 0, /* num_coords */ NULL, /* coords */ @@ -1598,7 +1597,7 @@ hb_font_set_ptem (hb_font_t *font, float ptem) * hb_font_get_ptem: * @font: a font. * - * Gets the "point size" of the font. A value of -1 means unset. + * Gets the "point size" of the font. A value of 0 means unset. * * Return value: Point size. * diff --git a/src/hb-font.h b/src/hb-font.h index 8fb1849de..540cdcab9 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -609,7 +609,7 @@ hb_font_get_ppem (hb_font_t *font, /* * Point size per EM. Used for optical-sizing in CoreText. - * A -1 means "not set". + * A value of zero means "not set". */ HB_EXTERN void hb_font_set_ptem (hb_font_t *font, float ptem); From 717fcb51dd051ca27d8537e5cf3a32d0447f78b5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:38:21 +0200 Subject: [PATCH 0450/1326] [coretext] Minor --- src/hb-coretext.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index a2bbfbd1f..c24ce70ce 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -37,7 +37,7 @@ #endif /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ -#define HB_CORETEXT_FONT_SIZE 12.0 +#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.0 static void release_table_data (void *user_data) @@ -74,7 +74,7 @@ hb_coretext_face_create (CGFontRef cg_font) HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, abs (CTFontGetSize((CTFontRef) data) - - (font->ptem <= 0 ? HB_CORETEXT_FONT_SIZE : font->ptem)) < 1) + (font->ptem <= 0 ? HB_CORETEXT_DEFAULT_FONT_SIZE : font->ptem)) < 1) /* * shaper face data @@ -247,7 +247,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); - float ptem = font->ptem <= 0 ? HB_CORETEXT_FONT_SIZE : font->ptem; + float ptem = font->ptem <= 0 ? HB_CORETEXT_DEFAULT_FONT_SIZE : font->ptem; CTFontRef ct_font = create_ct_font (cg_font, ptem); From e1b6d923021f68713784e2fd68f631c053ef3497 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 15:51:31 +0200 Subject: [PATCH 0451/1326] Remove cast of functions to (hb_destroy_func_t) Fixes https://github.com/behdad/harfbuzz/issues/474 --- src/hb-blob.cc | 8 +++++++- src/hb-coretext.cc | 10 ++++++++-- src/hb-face.cc | 6 ++++-- src/hb-ft.cc | 20 +++++++++++--------- src/hb-glib.cc | 9 ++++++++- src/hb-ot-font.cc | 6 ++++-- 6 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index fb48f03ca..41e99da0d 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -128,6 +128,12 @@ hb_blob_create (const char *data, return blob; } +static void +_hb_blob_destroy (void *data) +{ + hb_blob_destroy ((hb_blob_t *) data); +} + /** * hb_blob_create_sub_blob: * @parent: Parent blob. @@ -164,7 +170,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, MIN (length, parent->length - offset), HB_MEMORY_MODE_READONLY, hb_blob_reference (parent), - (hb_destroy_func_t) hb_blob_destroy); + _hb_blob_destroy); return blob; } diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index c24ce70ce..d899737d7 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -64,10 +64,16 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) release_table_data); } +static void +_hb_cg_font_release (void *data) +{ + CGFontRelease ((CGFontRef) data); +} + hb_face_t * hb_coretext_face_create (CGFontRef cg_font) { - return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease); + return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release); } @@ -116,7 +122,7 @@ static CGFontRef create_cg_font (hb_face_t *face) { CGFontRef cg_font = NULL; - if (face->destroy == (hb_destroy_func_t) CGFontRelease) + if (face->destroy == _hb_cg_font_release) { cg_font = CGFontRetain ((CGFontRef) face->user_data); } diff --git a/src/hb-face.cc b/src/hb-face.cc index d7d736d7b..0f90b59f3 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -118,8 +118,10 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) } static void -_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) +_hb_face_for_data_closure_destroy (void *data) { + hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data; + hb_blob_destroy (closure->blob); free (closure); } @@ -169,7 +171,7 @@ hb_face_create (hb_blob_t *blob, face = hb_face_create_for_tables (_hb_face_for_data_reference_table, closure, - (hb_destroy_func_t) _hb_face_for_data_closure_destroy); + _hb_face_for_data_closure_destroy); face->index = index; diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 492992ee4..c560b2196 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -95,14 +95,16 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) } static void -_hb_ft_face_destroy (FT_Face ft_face) +_hb_ft_face_destroy (void *data) { - FT_Done_Face (ft_face); + FT_Done_Face ((FT_Face) data); } static void -_hb_ft_font_destroy (hb_ft_font_t *ft_font) +_hb_ft_font_destroy (void *data) { + hb_ft_font_t *ft_font = (hb_ft_font_t *) data; + if (ft_font->unref) _hb_ft_face_destroy (ft_font->ft_face); @@ -124,7 +126,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) if (font->immutable) return; - if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + if (font->destroy != _hb_ft_font_destroy) return; hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; @@ -144,7 +146,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) int hb_ft_font_get_load_flags (hb_font_t *font) { - if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + if (font->destroy != _hb_ft_font_destroy) return 0; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; @@ -155,7 +157,7 @@ hb_ft_font_get_load_flags (hb_font_t *font) FT_Face hb_ft_font_get_face (hb_font_t *font) { - if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + if (font->destroy != _hb_ft_font_destroy) return NULL; const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; @@ -474,7 +476,7 @@ retry: hb_font_set_funcs (font, funcs, _hb_ft_font_create (ft_face, symbol, unref), - (hb_destroy_func_t) _hb_ft_font_destroy); + _hb_ft_font_destroy); } @@ -553,7 +555,7 @@ hb_face_t * hb_ft_face_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); + return hb_ft_face_create (ft_face, _hb_ft_face_destroy); } static void @@ -655,7 +657,7 @@ hb_font_t * hb_ft_font_create_referenced (FT_Face ft_face) { FT_Reference_Face (ft_face); - return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); + return hb_ft_font_create (ft_face, _hb_ft_face_destroy); } diff --git a/src/hb-glib.cc b/src/hb-glib.cc index 2b91b5b65..8b499558b 100644 --- a/src/hb-glib.cc +++ b/src/hb-glib.cc @@ -383,6 +383,13 @@ hb_glib_get_unicode_funcs (void) } #if GLIB_CHECK_VERSION(2,31,10) + +static void +_hb_g_bytes_unref (void *data) +{ + g_bytes_unref ((GBytes *) data); +} + /** * hb_glib_blob_create: * @@ -397,6 +404,6 @@ hb_glib_blob_create (GBytes *gbytes) size, HB_MEMORY_MODE_READONLY, g_bytes_ref (gbytes), - (hb_destroy_func_t) g_bytes_unref); + _hb_g_bytes_unref); } #endif diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index d3251caf7..a56f4c07f 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -458,8 +458,10 @@ _hb_ot_font_create (hb_face_t *face) } static void -_hb_ot_font_destroy (hb_ot_font_t *ot_font) +_hb_ot_font_destroy (void *data) { + hb_ot_font_t *ot_font = (hb_ot_font_t *) data; + ot_font->cmap.fini (); ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); @@ -627,5 +629,5 @@ hb_ot_font_set_funcs (hb_font_t *font) hb_font_set_funcs (font, _hb_ot_get_font_funcs (), ot_font, - (hb_destroy_func_t) _hb_ot_font_destroy); + _hb_ot_font_destroy); } From 94b3cafc3a042aea69ee7040227557fe98a21d87 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Oct 2017 17:22:44 +0200 Subject: [PATCH 0452/1326] Add hb_face_get_table_tags() New API: hb_face_get_table_tags() Fixes https://github.com/behdad/harfbuzz/issues/560 --- src/hb-face.cc | 29 +++++++++++++++++++++++++++++ src/hb-face.h | 5 +++++ src/hb-open-file-private.hh | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/hb-face.cc b/src/hb-face.cc index 0f90b59f3..e96c8acd3 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -474,4 +474,33 @@ hb_face_t::load_num_glyphs (void) const hb_blob_destroy (maxp_blob); } +/** + * hb_face_get_table_tags: + * @face: a face. + * + * Retrieves table tags for a face, if possible. + * + * Return value: total number of tables, or 0 if not possible to list. + * + * Since: 1.6.0 + **/ +unsigned int +hb_face_get_table_tags (hb_face_t *face, + unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */) +{ + if (face->destroy != _hb_face_for_data_closure_destroy) + { + if (table_count) + *table_count = 0; + return 0; + } + hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; + + const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer::lock_instance (data->blob); + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + + return ot_face.get_table_tags (start_offset, table_count, table_tags); +} diff --git a/src/hb-face.h b/src/hb-face.h index 91237b708..9842d52b6 100644 --- a/src/hb-face.h +++ b/src/hb-face.h @@ -111,6 +111,11 @@ hb_face_set_glyph_count (hb_face_t *face, HB_EXTERN unsigned int hb_face_get_glyph_count (hb_face_t *face); +HB_EXTERN unsigned int +hb_face_get_table_tags (hb_face_t *face, + unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */); HB_END_DECLS diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh index f208419aa..dcfdfd6ca 100644 --- a/src/hb-open-file-private.hh +++ b/src/hb-open-file-private.hh @@ -79,6 +79,24 @@ typedef struct OffsetTable if (unlikely (i >= numTables)) return Null(TableRecord); return tables[i]; } + inline unsigned int get_table_tags (unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */) const + { + if (table_count) + { + if (start_offset >= numTables) + *table_count = 0; + else + *table_count = MIN (*table_count, numTables - start_offset); + + const TableRecord *sub_tables = tables + start_offset; + unsigned int count = *table_count; + for (unsigned int i = 0; i < count; i++) + table_tags[i] = sub_tables[i].tag; + } + return numTables; + } inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const { Tag t; From 4e4781319b36bba154f3e5d4eb678945d8f6b4fc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 12 Oct 2017 10:33:16 +0200 Subject: [PATCH 0453/1326] [ft] Add hb_ft_font_changed() When the font size or variations settings on underlying FT_Face change, one can call hb_ft_font_changed() and continue using hb_font created using hb_ft_font_create(). Fixes https://github.com/behdad/harfbuzz/issues/559 New API: hb_ft_font_changed() --- docs/harfbuzz-sections.txt | 1 + src/hb-ft.cc | 15 +++++++++++++-- src/hb-ft.h | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 6d86d9418..06a78f5fa 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -291,6 +291,7 @@ hb_ft_face_create_cached hb_ft_face_create_referenced hb_ft_font_create hb_ft_font_create_referenced +hb_ft_font_changed hb_ft_font_get_face hb_ft_font_set_load_flags hb_ft_font_get_load_flags diff --git a/src/hb-ft.cc b/src/hb-ft.cc index c560b2196..83af9942e 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -610,6 +610,19 @@ hb_ft_font_create (FT_Face ft_face, font = hb_font_create (face); hb_face_destroy (face); _hb_ft_font_set_funcs (font, ft_face, false); + hb_ft_font_changed (font); + return font; +} + +void +hb_ft_font_changed (hb_font_t *font) +{ + if (font->destroy != _hb_ft_font_destroy) + return; + + hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; + FT_Face ft_face = ft_font->ft_face; + hb_font_set_scale (font, (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16), (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16)); @@ -640,8 +653,6 @@ hb_ft_font_create (FT_Face ft_face, free (mm_var); } #endif - - return font; } /** diff --git a/src/hb-ft.h b/src/hb-ft.h index dc8ef8558..94013eeb9 100644 --- a/src/hb-ft.h +++ b/src/hb-ft.h @@ -116,7 +116,13 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); HB_EXTERN int hb_ft_font_get_load_flags (hb_font_t *font); -/* Makes an hb_font_t use FreeType internally to implement font functions. */ +/* Call when size or variations settings on underlying FT_Face change. */ +HB_EXTERN void +hb_ft_font_changed (hb_font_t *font); + +/* Makes an hb_font_t use FreeType internally to implement font functions. + * Note: this internally creates an FT_Face. Use it when you create your + * hb_face_t using hb_face_create(). */ HB_EXTERN void hb_ft_font_set_funcs (hb_font_t *font); From dfeccd073a5e78f6a2c630355c04121b70d2b4aa Mon Sep 17 00:00:00 2001 From: ebraminio Date: Thu, 12 Oct 2017 12:11:47 +0330 Subject: [PATCH 0454/1326] Remove nmake port of harfbuzz (#562) --- BUILD.md | 12 +- Makefile.am | 2 +- appveyor.yml | 30 ----- configure.ac | 2 - win32/Makefile.am | 18 --- win32/Makefile.vc | 67 ---------- win32/README.txt | 97 -------------- win32/build-rules-msvc.mak | 130 ------------------ win32/config-msvc.mak | 230 -------------------------------- win32/config.h.win32.in | 158 ---------------------- win32/create-lists-msvc.mak | 147 -------------------- win32/create-lists.bat | 42 ------ win32/detectenv-msvc.mak | 146 -------------------- win32/generate-msvc.mak | 39 ------ win32/hb-introspection-msvc.mak | 42 ------ win32/info-msvc.mak | 162 ---------------------- win32/install.mak | 25 ---- win32/introspection-msvc.mak | 73 ---------- win32/pc_base.py | 124 ----------------- win32/replace.py | 115 ---------------- win32/sed-enums-srcs.py | 36 ----- win32/setup.py | 62 --------- 22 files changed, 9 insertions(+), 1750 deletions(-) delete mode 100644 win32/Makefile.am delete mode 100644 win32/Makefile.vc delete mode 100644 win32/README.txt delete mode 100644 win32/build-rules-msvc.mak delete mode 100644 win32/config-msvc.mak delete mode 100644 win32/config.h.win32.in delete mode 100644 win32/create-lists-msvc.mak delete mode 100644 win32/create-lists.bat delete mode 100644 win32/detectenv-msvc.mak delete mode 100644 win32/generate-msvc.mak delete mode 100644 win32/hb-introspection-msvc.mak delete mode 100644 win32/info-msvc.mak delete mode 100644 win32/install.mak delete mode 100644 win32/introspection-msvc.mak delete mode 100644 win32/pc_base.py delete mode 100644 win32/replace.py delete mode 100644 win32/sed-enums-srcs.py delete mode 100644 win32/setup.py diff --git a/BUILD.md b/BUILD.md index 7518c2e42..370c997ac 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,7 +5,13 @@ Cairo, and GLib. For example, on Ubuntu / Debian, you would do: whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do: * sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel -on the Mac, using MacPorts: +on Windows, consider using [vcpkg](https://github.com/Microsoft/vcpkg), +provided by Microsoft, for building HarfBuzz and other open-source libraries +but if you need to build harfbuzz from source, put ragel binary on your +PATH and follow appveyor CI's cmake +[https://github.com/behdad/harfbuzz/blob/master/appveyor.yml](build steps). + +on macOS, using MacPorts: * sudo port install freetype glib2 cairo or using Homebrew: @@ -14,9 +20,7 @@ or using Homebrew: If you are using a tarball, you can now proceed to running configure and make as with any other standard package. That should leave you with a shared library in src/, and a few utility programs including hb-view and hb-shape -under util/. From the tarball, NMake Makefiles are also provided in win32/, -which supports building HarfBuzz using Visual Studio, with a README.txt that -gives instructions on building using NMake. +under util/. If you are bootstraping from git, you need a few more tools before you can run autogen.sh for the first time. Namely, pkg-config and ragel. Again, on Ubuntu / Debian: diff --git a/Makefile.am b/Makefile.am index 1755b73b6..07b38c287 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ NULL = ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src util test docs win32 +SUBDIRS = src util test docs EXTRA_DIST = \ autogen.sh \ diff --git a/appveyor.yml b/appveyor.yml index 3d3f77742..c27a899f9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,23 +15,6 @@ environment: platform: ARM configuration: Debug - - compiler: nmake - ARCH: amd64 - VCPKG_ARCH: x64-windows - CFG: debug - - compiler: nmake - ARCH: x86 - VCPKG_ARCH: x86-windows - CFG: debug -# - compiler: nmake -# ARCH: amd64 -# VCPKG_ARCH: x64-windows -# CFG: release -# - compiler: nmake -# ARCH: x86 -# VCPKG_ARCH: x86-windows -# CFG: release - - compiler: msys2 MINGW_PREFIX: /c/msys2/mingw64/ MINGW_CHOST: x86_64-w64-mingw32 @@ -44,14 +27,6 @@ environment: install: - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-ragel" - - 'if "%compiler%"=="nmake" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH%' -# - 'if "%compiler%"=="nmake" git clone https://github.com/Microsoft/vcpkg' -# - 'if "%compiler%"=="nmake" cd vcpkg' -# - 'if "%compiler%"=="nmake" powershell -exec bypass scripts\bootstrap.ps1' -# - 'if "%compiler%"=="nmake" vcpkg install freetype:%VCPKG_ARCH%' -# - 'if "%compiler%"=="nmake" copy installed\%VCPKG_ARCH%\debug\lib\freetyped.lib installed\%VCPKG_ARCH%\lib' -# - 'if "%compiler%"=="nmake" cd ..' - build_script: - 'if "%compiler%"=="cmake" md build' - 'if "%compiler%"=="cmake" cd build' @@ -59,11 +34,6 @@ build_script: - 'if "%compiler%"=="cmake" cmake -DHB_HAVE_UNISCRIBE=ON -DHB_HAVE_DIRECTWRITE=ON -G "%generator%" ../' - 'if "%compiler%"=="cmake" msbuild harfbuzz.sln /p:Configuration=%configuration% /p:Platform=%platform%' - - 'if "%compiler%"=="nmake" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh; make distdir"' - - 'if "%compiler%"=="nmake" cd harfbuzz-*\win32' - - 'if "%compiler%"=="nmake" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1' # FREETYPE=1 FREETYPE_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\include ADDITIONAL_LIB_DIR=..\..\vcpkg\installed\%VCPKG_ARCH%\lib' - - 'if "%compiler%"=="nmake" nmake /f Makefile.vc CFG=%CFG% UNISCRIBE=1 DIRECTWRITE=1 install' # FREETYPE=1 install' - - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config}"' - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || (cat */test-suite.log test/*/test-suite.log && false)"' diff --git a/configure.ac b/configure.ac index d65cae8cd..7b947f276 100644 --- a/configure.ac +++ b/configure.ac @@ -494,8 +494,6 @@ test/fuzzing/Makefile test/shaping/Makefile docs/Makefile docs/version.xml -win32/Makefile -win32/config.h.win32 ]) AC_OUTPUT diff --git a/win32/Makefile.am b/win32/Makefile.am deleted file mode 100644 index 79ce999da..000000000 --- a/win32/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -EXTRA_DIST = \ - build-rules-msvc.mak \ - config-msvc.mak \ - config.h.win32 \ - create-lists.bat \ - create-lists-msvc.mak \ - detectenv-msvc.mak \ - generate-msvc.mak \ - hb-introspection-msvc.mak \ - info-msvc.mak \ - install.mak \ - introspection-msvc.mak \ - Makefile.vc \ - README.txt \ - replace.py \ - sed-enums-srcs.py - --include $(top_srcdir)/git.mk diff --git a/win32/Makefile.vc b/win32/Makefile.vc deleted file mode 100644 index 05778ae54..000000000 --- a/win32/Makefile.vc +++ /dev/null @@ -1,67 +0,0 @@ -# NMake Makefile for building HarfBuzz as a DLL on Windows - -# The items below this line should not be changed, unless one is maintaining -# the NMake Makefiles. Customizations can be done in the following NMake Makefile -# portions (please see comments in the these files to see what can be customized): -# -# detectenv-msvc.mak -# config-msvc.mak - -!include detectenv-msvc.mak - -# Include the Makefile portions with the source listings -!include ..\src\Makefile.sources -!include ..\src\hb-ucdn\Makefile.sources -!include ..\util\Makefile.sources - -# We need to include the sources in ..\src\hb-ucdn indirectly -!if [call create-lists.bat header hb_ucdn_srcs.mak hb_ucdn_SRCS] -!endif - -!if [for %c in ($(LIBHB_UCDN_sources)) do @call create-lists.bat file hb_ucdn_srcs.mak hb-ucdn\%c] -!endif - -!if [call create-lists.bat footer hb_ucdn_srcs.mak] -!endif - -!include hb_ucdn_srcs.mak - -!if [del /f /q hb_ucdn_srcs.mak] -!endif - -# Include the Makefile portion that enables features based on user input -!include config-msvc.mak - -!if "$(VALID_CFGSET)" == "TRUE" - -# Include the Makefile portion to convert the source and header lists -# into the lists we need for compilation and introspection -!include create-lists-msvc.mak - -all: $(HB_LIBS) $(HB_UTILS) $(EXTRA_TARGETS) all-build-info - -tests: all $(HB_TESTS) - -# Include the build rules for sources, DLLs and executables -!include build-rules-msvc.mak - -# Include the rules for build directory creation and code generation -!include generate-msvc.mak - -# Generate the introspection files - -!if "$(INTROSPECTION)" == "1" -# Include the rules for building the introspection files -!include introspection-msvc.mak -!include hb-introspection-msvc.mak -!endif - -!include install.mak - -!else -all: help - @echo You need to specify a valid configuration, via - @echo CFG=release or CFG=debug -!endif - -!include info-msvc.mak diff --git a/win32/README.txt b/win32/README.txt deleted file mode 100644 index 185a44c3e..000000000 --- a/win32/README.txt +++ /dev/null @@ -1,97 +0,0 @@ -Instructions for building HarfBuzz on Visual Studio -=================================================== -Building the HarfBuzz DLL on Windows is now also supported using Visual Studio -versions 2008 through 2015, in both 32-bit and 64-bit (x64) flavors, via NMake -Makefiles. - -The following are instructions for performing such a build, as there is a -number of build configurations supported for the build. Note that for all -build configurations, the OpenType and Simple TrueType layout (fallback) -backends are enabled, and this is the base configuration that is built if no -options (see below) are specified. A 'clean' target is provided-it is recommended -that one cleans the build and redo the build if any configuration option changed. -An 'install' target is also provided to copy the built items in their appropriate -locations under $(PREFIX), which is described below. A 'reallyclean' target is -provided that not only does what is done for the 'clean' target, but also removes -the sources/headers that are generated from the Ragel sources. Therefore, if one -is not building from a release tarball, or is rebuilding after using the 'reallyclean' -target or when the Ragel (*.rl) sources are updated, the Ragel state machine -compiler (ragel.exe) is needed, and needs to be passed in via RAGEL= -if ragel.exe is not already in the PATH. - -We now support building from a GIT checkout via NMake for convenience. In addition to -the requirements as outlined in the later part of this file, you will need to run the -setup.py (Python 2.7.x or later) script to generate the headers (src\hb-version.h and -win32\config.h.win32) that are normally shipped in a release tarball before running -NMake, and you will need to pass RAGEL= if the Ragel state machine -compiler (ragel.exe) is not in your PATH when invoking NMake. Note that the -'reallyclean' target does not remove these 2 generated headers, so re-run the setup.py -script if necessary. - -Invoke the build by issuing the command: -nmake /f Makefile.vc CFG=[release|debug] [PREFIX=...] -where: - -CFG: Required. Choose from a release or debug build. Note that - all builds generate a .pdb file for each .dll and .exe built--this refers - to the C/C++ runtime that the build uses. - -PREFIX: Optional. Base directory of where the third-party headers, libraries - and needed tools can be found, i.e. headers in $(PREFIX)\include, - libraries in $(PREFIX)\lib and tools in $(PREFIX)\bin. If not - specified, $(PREFIX) is set as $(srcroot)\..\vs$(X)\$(platform), where - $(platform) is win32 for 32-bit builds or x64 for 64-bit builds, and - $(X) is the short version of the Visual Studio used, as follows: - 2008: 9 - 2010: 10 - 2012: 11 - 2013: 12 - 2015: 14 - 2017: 15 - -Explanation of options, set by