diff options
author | Khaled Hosny <khaledhosny@eglug.org> | 2019-07-19 11:52:13 +0200 |
---|---|---|
committer | Khaled Hosny <khaledhosny@eglug.org> | 2019-07-19 11:52:13 +0200 |
commit | e62e0953e5a4153e194ca18fe5607c70d6011455 (patch) | |
tree | 75d4e6c796ecb0ad0c9e8f7992f2f9c6214ed9ef | |
parent | 24e079c3ef47702a38266d404aac204b701038ad (diff) | |
download | pango-e62e0953e5a4153e194ca18fe5607c70d6011455.tar.gz |
Remove now unused platform shaping code
-rw-r--r-- | pango/meson.build | 5 | ||||
-rw-r--r-- | pango/pangocoretext-private.h | 9 | ||||
-rw-r--r-- | pango/pangocoretext-shape.c | 554 | ||||
-rw-r--r-- | pango/pangowin32-private.h | 10 | ||||
-rw-r--r-- | pango/pangowin32-shape.c | 775 |
5 files changed, 0 insertions, 1353 deletions
diff --git a/pango/meson.build b/pango/meson.build index cfbf8a9a..1327ca39 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -340,14 +340,10 @@ if host_system == 'windows' 'pangowin32.c', 'pangowin32-fontcache.c', 'pangowin32-fontmap.c', - 'pangowin32-shape.c', ] - # usp10 needs to be before gdi32 - # see https://bugzilla.gnome.org/show_bug.cgi?id=795045#c0 pangowin32_deps = pango_deps + [ libpango_dep, - cc.find_library('usp10'), cc.find_library('gdi32'), ] @@ -441,7 +437,6 @@ if cairo_dep.found() pangocairo_sources += [ 'pangocoretext.c', 'pangocoretext-fontmap.c', - 'pangocoretext-shape.c', 'pangocairo-coretextfont.c', 'pangocairo-coretextfontmap.c', ] diff --git a/pango/pangocoretext-private.h b/pango/pangocoretext-private.h index a652f520..57d26937 100644 --- a/pango/pangocoretext-private.h +++ b/pango/pangocoretext-private.h @@ -155,15 +155,6 @@ PangoGravity pango_core_text_font_key_get_gravity (const Pango _PANGO_EXTERN CTFontDescriptorRef pango_core_text_font_key_get_ctfontdescriptor (const PangoCoreTextFontKey *key); -void -_pango_core_text_shape (PangoFont *font, - const char *text, - gint length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - const char *paragraph_text G_GNUC_UNUSED, - unsigned int paragraph_length G_GNUC_UNUSED); - G_END_DECLS #endif /* __PANGOCORETEXT_PRIVATE_H__ */ diff --git a/pango/pangocoretext-shape.c b/pango/pangocoretext-shape.c deleted file mode 100644 index 061279a9..00000000 --- a/pango/pangocoretext-shape.c +++ /dev/null @@ -1,554 +0,0 @@ -/* Pango - * pangocoretext-shape.c - * - * Copyright (C) 2005 Imendio AB - * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org> - * Copyright (C) 2012 Kristian Rietveld <kris@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" -#include <glib.h> -#include <string.h> -#include <Carbon/Carbon.h> -#include "pango-utils.h" -#include "pangocoretext-private.h" -#include "pango-impl-utils.h" - -#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < 1060 -CF_INLINE Boolean CFStringIsSurrogateHighCharacter(UniChar character) { - return ((character >= 0xD800UL) && (character <= 0xDBFFUL) ? true : false); -} - -CF_INLINE Boolean CFStringIsSurrogateLowCharacter(UniChar character) { - return ((character >= 0xDC00UL) && (character <= 0xDFFFUL) ? true : false); -} - -CF_INLINE UTF32Char CFStringGetLongCharacterForSurrogatePair(UniChar surrogateHigh, UniChar surrogateLow) { - return ((surrogateHigh - 0xD800UL) << 10) + (surrogateLow - 0xDC00UL) + 0x0010000UL; -} -#endif - -static void -set_glyph (PangoFont *font, - PangoGlyphString *glyphs, - int i, - int offset, - PangoGlyph glyph) -{ - PangoRectangle logical_rect; - - glyphs->glyphs[i].glyph = glyph; - - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - - glyphs->log_clusters[i] = offset; - pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect); - glyphs->glyphs[i].geometry.width = logical_rect.width; -} - - -/* The "RunIterator" helps us to iterate over the array of runs that is obtained from - * the CoreText type setter. Even though Pango considers the string that is passed to - * the shape function a single run, CoreText might consider it to consist out of - * multiple runs. Because of this, we have an interface around the CoreText array of - * runs that works like iterating a single array, which makes our job in the shape - * function easier. - */ - -struct RunIterator -{ - CTLineRef line; - CFStringRef cstr; - CFArrayRef runs; - CFIndex glyph_count; - - CFIndex total_ct_i; - CFIndex ct_i; - - CFIndex *chr_idx_lut; - - int current_run_number; - CTRunRef current_run; - CFIndex *current_indices; - const CGGlyph *current_cgglyphs; - CGGlyph *current_cgglyphs_buffer; - CTRunStatus current_run_status; -}; - -static void -run_iterator_free_current_run (struct RunIterator *iter) -{ - iter->current_run_number = -1; - iter->current_run = NULL; - iter->current_cgglyphs = NULL; - if (iter->current_cgglyphs_buffer) - free (iter->current_cgglyphs_buffer); - iter->current_cgglyphs_buffer = NULL; - if (iter->current_indices) - free (iter->current_indices); - iter->current_indices = NULL; -} - -static void -run_iterator_set_current_run (struct RunIterator *iter, - const int run_number) -{ - CFIndex ct_glyph_count; - - run_iterator_free_current_run (iter); - - iter->current_run_number = run_number; - iter->current_run = CFArrayGetValueAtIndex (iter->runs, run_number); - ct_glyph_count = CTRunGetGlyphCount (iter->current_run); - - iter->current_run_status = CTRunGetStatus (iter->current_run); - iter->current_cgglyphs = CTRunGetGlyphsPtr (iter->current_run); - if (!iter->current_cgglyphs) - { - iter->current_cgglyphs_buffer = (CGGlyph *)malloc (sizeof (CGGlyph) * ct_glyph_count); - CTRunGetGlyphs (iter->current_run, CFRangeMake (0, ct_glyph_count), - iter->current_cgglyphs_buffer); - iter->current_cgglyphs = iter->current_cgglyphs_buffer; - } - - iter->current_indices = malloc (sizeof (CFIndex) * ct_glyph_count); - CTRunGetStringIndices (iter->current_run, CFRangeMake (0, ct_glyph_count), - iter->current_indices); - - iter->ct_i = 0; -} - -static CFIndex -run_iterator_get_glyph_count (struct RunIterator *iter) -{ - CFIndex accumulator = 0; - CFIndex i; - - for (i = 0; i < CFArrayGetCount (iter->runs); i++) - accumulator += CTRunGetGlyphCount (CFArrayGetValueAtIndex (iter->runs, i)); - - return accumulator; -} - -/* This function generates a lookup table to match string indices of glyphs to - * actual unicode character indices. This also takes unicode characters into - * account that are encoded using 2 UTF16 code points in CFStrings. We use the - * unicode character index to match up with the unicode characters in the UTF8 - * string provided by Pango. - */ -static CFIndex * -run_iterator_get_chr_idx_lut (CFStringRef cstr) -{ - CFIndex cstr_length = CFStringGetLength (cstr); - CFIndex *chr_idx_lut = malloc (sizeof (CFIndex) * cstr_length); - CFIndex i; - CFIndex current_value = 0; - - for (i = 0; i < cstr_length; i++) - { - chr_idx_lut[i] = current_value; - - if (CFStringIsSurrogateHighCharacter (CFStringGetCharacterAtIndex (cstr, i)) && - i + 1 < cstr_length && - CFStringIsSurrogateLowCharacter (CFStringGetCharacterAtIndex (cstr, i + 1))) - continue; - - current_value++; - } - - return chr_idx_lut; -} - -/* These functions are commented out to silence the compiler, but - * kept around because they might be of use when fixing the more - * intricate issues noted in the comment in the function - * pangocoretext_shape() below. - */ -#if 0 -static gboolean -run_iterator_is_rtl (struct RunIterator *iter) -{ - /* Assume run status is equal for all runs? */ - CTRunStatus run_status = CTRunGetStatus (CFArrayGetValueAtIndex (iter->runs, 0)); - - return run_status & kCTRunStatusRightToLeft; -} - -static gboolean -run_iterator_run_is_non_monotonic (struct RunIterator *iter) -{ - CTRunStatus run_status = CTRunGetStatus (iter->current_run); - - return run_status & kCTRunStatusNonMonotonic; -} -#endif - -static gunichar -run_iterator_get_character (struct RunIterator *iter) -{ - UniChar ch = CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]); - - if (CFStringIsSurrogateHighCharacter (ch) && - iter->current_indices[iter->ct_i] + 1 < CFStringGetLength (iter->cstr)) - { - UniChar ch2 = CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]+1); - - if (CFStringIsSurrogateLowCharacter (ch2)) - return CFStringGetLongCharacterForSurrogatePair (ch, ch2); - } - - return ch; -} - -static CGGlyph -run_iterator_get_cgglyph (struct RunIterator *iter) -{ - return iter->current_cgglyphs[iter->ct_i]; -} - -static CFIndex -run_iterator_get_index (struct RunIterator *iter) -{ - return iter->chr_idx_lut[iter->current_indices[iter->ct_i]]; -} - -static gboolean -run_iterator_create (struct RunIterator *iter, - const char *text, - const gint length, - CTFontRef ctfont) -{ - char *copy; - CFDictionaryRef attributes; - CFAttributedStringRef attstr; - - CFTypeRef keys[] = { - (CFTypeRef) kCTFontAttributeName - }; - - CFTypeRef values[] = { - ctfont - }; - - /* Initialize RunIterator structure */ - iter->current_run_number = -1; - iter->current_run = NULL; - iter->current_indices = NULL; - iter->chr_idx_lut = NULL; - iter->current_cgglyphs = NULL; - iter->current_cgglyphs_buffer = NULL; - - /* Create CTLine */ - attributes = CFDictionaryCreate (kCFAllocatorDefault, - (const void **)keys, - (const void **)values, - 1, - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - copy = g_strndup (text, length + 1); - copy[length] = 0; - - iter->cstr = CFStringCreateWithCString (kCFAllocatorDefault, copy, - kCFStringEncodingUTF8); - g_free (copy); - - if (!iter->cstr) - /* Creating a CFString can fail if the input string does not - * adhere to the specified encoding (i.e. it contains invalid UTF8). - */ - return FALSE; - - attstr = CFAttributedStringCreate (kCFAllocatorDefault, - iter->cstr, - attributes); - - iter->line = CTLineCreateWithAttributedString (attstr); - iter->runs = CTLineGetGlyphRuns (iter->line); - - CFRelease (attstr); - CFRelease (attributes); - - iter->chr_idx_lut = run_iterator_get_chr_idx_lut (iter->cstr); - - iter->total_ct_i = 0; - iter->glyph_count = run_iterator_get_glyph_count (iter); - - /* If CoreText did not render any glyphs for this string (can happen, - * e.g. a run solely consisting of a BOM), glyph_count will be zero and - * we immediately set the iterator variable to indicate end of glyph list. - */ - if (iter->glyph_count > 0) - run_iterator_set_current_run (iter, 0); - else - iter->total_ct_i = -1; - - return TRUE; -} - -static void -run_iterator_free (struct RunIterator *iter) -{ - run_iterator_free_current_run (iter); - - free (iter->chr_idx_lut); - - CFRelease (iter->line); - CFRelease (iter->cstr); -} - -static gboolean -run_iterator_at_end (struct RunIterator *iter) -{ - if (iter->total_ct_i == -1) - return TRUE; - - return FALSE; -} - -static void -run_iterator_advance (struct RunIterator *iter) -{ - if (iter->total_ct_i >= iter->glyph_count - 1) - { - run_iterator_free_current_run (iter); - iter->ct_i = iter->total_ct_i = -1; - } - else - { - iter->total_ct_i++; - iter->ct_i++; - - if (iter->total_ct_i < iter->glyph_count && - iter->ct_i >= CTRunGetGlyphCount (iter->current_run)) - { - iter->current_run_number++; - run_iterator_set_current_run (iter, iter->current_run_number); - } - } -} - - - -struct GlyphInfo -{ - CFIndex index; - CGGlyph cgglyph; - gunichar wc; -}; - -static gint -glyph_info_compare_func (gconstpointer a, gconstpointer b) -{ - const struct GlyphInfo *gi_a = a; - const struct GlyphInfo *gi_b = b; - - if (gi_a->index < gi_b->index) - return -1; - else if (gi_a->index > gi_b->index) - return 1; - /* else */ - return 0; -} - -static void -glyph_info_free (gpointer data, gpointer user_data) -{ - g_slice_free (struct GlyphInfo, data); -} - -static GSList * -create_core_text_glyph_list (const char *text, - gint length, - CTFontRef ctfont) -{ - GSList *glyph_list = NULL; - struct RunIterator riter; - - if (!run_iterator_create (&riter, text, length, ctfont)) - return NULL; - - while (!run_iterator_at_end (&riter)) - { - struct GlyphInfo *gi; - - gi = g_slice_new (struct GlyphInfo); - gi->index = run_iterator_get_index (&riter); - gi->cgglyph = run_iterator_get_cgglyph (&riter); - gi->wc = run_iterator_get_character (&riter); - - glyph_list = g_slist_prepend (glyph_list, gi); - - run_iterator_advance (&riter); - } - - glyph_list = g_slist_sort (glyph_list, glyph_info_compare_func); - - run_iterator_free (&riter); - - return glyph_list; -} - - -void -_pango_core_text_shape (PangoFont *font, - const char *text, - gint length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - const char *paragraph_text G_GNUC_UNUSED, - unsigned int paragraph_length G_GNUC_UNUSED) -{ - const char *p; - gulong n_chars, gs_i, gs_prev_i; - PangoCoreTextFont *cfont = PANGO_CORE_TEXT_FONT (font); - PangoCoverage *coverage; - GSList *glyph_list; - GSList *glyph_iter; - - /* We first fully iterate over the glyph sequence generated by CoreText and - * store this into a list, which is sorted after the iteration. We make a pass - * over the sorted linked list to build up the PangoGlyphString. - * - * We have to do this in order to properly handle a bunch of characteristics of the - * glyph sequence generated by the CoreText typesetter: - * # E.g. zero-width spaces do not end up in the CoreText glyph sequence. We have - * to manually account for the gap in the character indices. - * # Sometimes, CoreText generates two glyph for the same character index. We - * currently handle this "properly" as in we do not crash or corrupt memory, - * but that's about it. - * # Due to mismatches in size, the CoreText glyph sequence can either be longer or - * shorter than the PangoGlyphString. Note that the size of the PangoGlyphString - * should match the number of characters in "text". - * - * If performance becomes a problem, it is certainly possible to use a faster code - * that only does a single iteration over the string for "simple cases". Simple cases - * could include these that only consist out of one run (simple Latin text), which - * don't have gaps in the glyph sequence and which are monotonically - * increasing/decreasing. - * - * FIXME items for future fixing: - * # We currently don't bother about LTR, Pango core appears to fix this up for us. - * (Even when we cared warnings were generated that strings were in the wrong - * order, this should be investigated). - * # When CoreText generates two glyphs for one character, only one is stored. - * This breaks the example strings for e.g. Georgian and Gothic. - */ - - glyph_list = create_core_text_glyph_list (text, length, - pango_core_text_font_get_ctfont (cfont)); - if (!glyph_list) - return; - - /* Set up for translation of the glyph list to a PangoGlyphString. */ - n_chars = pango_utf8_strlen (text, length); - pango_glyph_string_set_size (glyphs, n_chars); - - glyph_iter = glyph_list; - - coverage = pango_font_get_coverage (PANGO_FONT (cfont), - analysis->language); - - /* gs_i is the index into the Pango glyph string. gi is the iterator into - * the (CoreText) glyph list, gi->index is the index into the CFString. - * In matching, we want gs_i and gi->index to match up. - */ - for (gs_prev_i = -1, gs_i = 0, p = text; gs_i < n_chars; - gs_prev_i = gs_i, gs_i++, p = g_utf8_next_char (p)) - { - struct GlyphInfo *gi = glyph_iter != NULL ? glyph_iter->data : NULL; - - if (gi == NULL || gi->index > gs_i) - { - /* The glyph string is behind, insert an empty glyph to catch - * up with the CoreText glyph list. This occurs for instance when - * CoreText inserts a ligature that covers two characters. - */ - set_glyph (font, glyphs, gs_i, p - text, PANGO_GLYPH_EMPTY); - continue; - } - else if (gi->index < gs_i) - { - /* The CoreText glyph list is behind, fast forward the iterator - * to catch up. This can happen when CoreText emits two glyphs - * for once character, which is (as noted in the FIXME) above - * not handled by us yet. - */ - while (gi && gi->index < gs_i) - { - glyph_iter = g_slist_next (glyph_iter); - if (glyph_iter) - gi = glyph_iter->data; - else - gi = NULL; - } - } - - if (gi != NULL && gi->index == gs_i) - { - gunichar mirrored_ch; - PangoCoverageLevel result; - - if (analysis->level % 2) - if (g_unichar_get_mirror_char (gi->wc, &mirrored_ch)) - gi->wc = mirrored_ch; - - if (gi->wc == 0xa0) /* non-break-space */ - gi->wc = 0x20; - - result = pango_coverage_get (coverage, gi->wc); - - if (result != PANGO_COVERAGE_NONE) - { - set_glyph (font, glyphs, gs_i, p - text, gi->cgglyph); - - if (g_unichar_type (gi->wc) == G_UNICODE_NON_SPACING_MARK) - { - if (gi->index > 0) - { - PangoRectangle logical_rect, ink_rect; - - glyphs->glyphs[gs_i].geometry.width = MAX (glyphs->glyphs[gs_prev_i].geometry.width, - glyphs->glyphs[gs_i].geometry.width); - glyphs->glyphs[gs_prev_i].geometry.width = 0; - glyphs->log_clusters[gs_i] = glyphs->log_clusters[gs_prev_i]; - - /* Some heuristics to try to guess how overstrike glyphs are - * done and compensate - */ - pango_font_get_glyph_extents (font, glyphs->glyphs[gs_i].glyph, &ink_rect, &logical_rect); - if (logical_rect.width == 0 && ink_rect.x == 0) - glyphs->glyphs[gs_i].geometry.x_offset = (glyphs->glyphs[gs_i].geometry.width - ink_rect.width) / 2; - } - } - } - else - set_glyph (font, glyphs, gs_i, p - text, PANGO_GET_UNKNOWN_GLYPH (gi->wc)); - - glyph_iter = g_slist_next (glyph_iter); - } - } - - pango_coverage_unref (coverage); - g_slist_foreach (glyph_list, glyph_info_free, NULL); - g_slist_free (glyph_list); - - if (analysis->level & 1) - pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs); -} diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h index fd102413..65f9de05 100644 --- a/pango/pangowin32-private.h +++ b/pango/pangowin32-private.h @@ -284,16 +284,6 @@ gboolean _pango_win32_get_name_record (HDC hdc, _PANGO_EXTERN HFONT _pango_win32_font_get_hfont (PangoFont *font); -_PANGO_EXTERN -void -_pango_win32_shape (PangoFont *font, - const char *text, - unsigned int length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - const char *paragraph_text G_GNUC_UNUSED, - unsigned int paragraph_length G_GNUC_UNUSED); - extern HDC _pango_win32_hdc; extern OSVERSIONINFO _pango_win32_os_version_info; extern gboolean _pango_win32_debug; diff --git a/pango/pangowin32-shape.c b/pango/pangowin32-shape.c deleted file mode 100644 index aad0243e..00000000 --- a/pango/pangowin32-shape.c +++ /dev/null @@ -1,775 +0,0 @@ -/* Pango - * pangowin32-shape.c: - * - * Copyright (C) 1999 Red Hat Software - * Copyright (C) 2001 Alexander Larsson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -/*#define BASIC_WIN32_DEBUGGING */ - -#include <math.h> -#include <stdlib.h> - -#include <glib.h> - -#include "pangowin32-private.h" - -#include "pango-utils.h" -#include "pango-impl-utils.h" - -static gboolean pango_win32_debug = FALSE; - -#include <usp10.h> - -static PangoGlyph -find_char (PangoFont *font, - gunichar wc) -{ - return pango_win32_font_get_glyph_index (font, wc); -} - -static void -set_glyph (PangoFont *font, - PangoGlyphString *glyphs, - int i, - int offset, - PangoGlyph glyph) -{ - PangoRectangle logical_rect; - - glyphs->glyphs[i].glyph = glyph; - - glyphs->glyphs[i].geometry.x_offset = 0; - glyphs->glyphs[i].geometry.y_offset = 0; - - glyphs->log_clusters[i] = offset; - - pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect); - glyphs->glyphs[i].geometry.width = logical_rect.width; -} - -static void -swap_range (PangoGlyphString *glyphs, - int start, - int end) -{ - int i, j; - - for (i = start, j = end - 1; i < j; i++, j--) - { - PangoGlyphInfo glyph_info; - gint log_cluster; - - glyph_info = glyphs->glyphs[i]; - glyphs->glyphs[i] = glyphs->glyphs[j]; - glyphs->glyphs[j] = glyph_info; - - log_cluster = glyphs->log_clusters[i]; - glyphs->log_clusters[i] = glyphs->log_clusters[j]; - glyphs->log_clusters[j] = log_cluster; - } -} - -#ifdef BASIC_WIN32_DEBUGGING - -static char * -lang_name (int lang) -{ - LCID lcid = MAKELCID (lang, SORT_DEFAULT); - static char retval[10]; - - if (!GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, retval, G_N_ELEMENTS (retval))) - sprintf (retval, "%#02x", lang); - - return retval; -} - -#endif /* BASIC_WIN32_DEBUGGING */ - -static WORD -make_langid (PangoLanguage *lang) -{ -#define CASE(t,p,s) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_##p##_##s) -#define CASEN(t,p) if (pango_language_matches (lang, t)) return MAKELANGID (LANG_##p, SUBLANG_NEUTRAL) - - /* Languages that most probably don't affect Uniscribe have been - * left out. Uniscribe is documented to use - * SCRIPT_CONTROL::uDefaultLanguage only to select digit shapes, so - * just leave languages with own digits. - */ - - CASEN ("ar", ARABIC); - CASEN ("hy", ARMENIAN); - CASEN ("as", ASSAMESE); - CASEN ("az", AZERI); - CASEN ("bn", BENGALI); - CASE ("zh-tw", CHINESE, TRADITIONAL); - CASE ("zh-cn", CHINESE, SIMPLIFIED); - CASE ("zh-hk", CHINESE, HONGKONG); - CASE ("zh-sg", CHINESE, SINGAPORE); - CASE ("zh-mo", CHINESE, MACAU); - CASEN ("dib", DIVEHI); - CASEN ("fa", FARSI); - CASEN ("ka", GEORGIAN); - CASEN ("gu", GUJARATI); - CASEN ("he", HEBREW); - CASEN ("hi", HINDI); - CASEN ("ja", JAPANESE); - CASEN ("kn", KANNADA); - CASE ("ks-in", KASHMIRI, INDIA); - CASEN ("ks", KASHMIRI); - CASEN ("kk", KAZAK); - CASEN ("kok", KONKANI); - CASEN ("ko", KOREAN); - CASEN ("ky", KYRGYZ); - CASEN ("ml", MALAYALAM); - CASEN ("mni", MANIPURI); - CASEN ("mr", MARATHI); - CASEN ("mn", MONGOLIAN); - CASE ("ne-in", NEPALI, INDIA); - CASEN ("ne", NEPALI); - CASEN ("or", ORIYA); - CASEN ("pa", PUNJABI); - CASEN ("sa", SANSKRIT); - CASEN ("sd", SINDHI); - CASEN ("syr", SYRIAC); - CASEN ("ta", TAMIL); - CASEN ("tt", TATAR); - CASEN ("te", TELUGU); - CASEN ("th", THAI); - CASE ("ur-pk", URDU, PAKISTAN); - CASE ("ur-in", URDU, INDIA); - CASEN ("ur", URDU); - CASEN ("uz", UZBEK); - -#undef CASE -#undef CASEN - - return MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL); -} - -#ifdef BASIC_WIN32_DEBUGGING - -static void -dump_glyphs_and_log_clusters (gboolean rtl, - int itemlen, - int charix0, - WORD *log_clusters, - WORD *iglyphs, - int nglyphs) -{ - if (pango_win32_debug) - { - int j, k, nclusters, clusterix, charix, ng; - - g_print (" ScriptShape: nglyphs=%d: ", nglyphs); - - for (j = 0; j < nglyphs; j++) - g_print ("%d%s", iglyphs[j], (j < nglyphs-1) ? "," : ""); - g_print ("\n"); - - g_print (" log_clusters: "); - for (j = 0; j < itemlen; j++) - g_print ("%d ", log_clusters[j]); - g_print ("\n"); - nclusters = 0; - for (j = 0; j < itemlen; j++) - { - if (j == 0 || log_clusters[j-1] != log_clusters[j]) - nclusters++; - } - g_print (" %d clusters:\n", nclusters); - - /* If RTL, first char is the last in the run, otherwise the - * first. - */ - clusterix = 0; - if (rtl) - { - int firstglyphix = 0; - for (j = itemlen - 1, charix = charix0 + j; j >= 0; j--, charix--) - { - if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1]) - g_print (" Cluster %d: chars %d--", - clusterix, charix); - if (j == 0 || log_clusters[j-1] != log_clusters[j]) - { - ng = log_clusters[j] - firstglyphix + 1; - g_print ("%d: %d glyphs: ", - charix, ng); - for (k = firstglyphix; k <= log_clusters[j]; k++) - { - g_print ("%d", iglyphs[k]); - if (k < log_clusters[j]) - g_print (","); - } - firstglyphix = log_clusters[j] + 1; - clusterix++; - g_print ("\n"); - } - } - } - else - { - for (j = 0, charix = charix0; j < itemlen; j++, charix++) - { - if (j == 0 || log_clusters[j-1] != log_clusters[j]) - g_print (" Cluster %d: wchar_t %d--", - clusterix, charix); - if (j == itemlen - 1 || log_clusters[j] != log_clusters[j+1]) - { - int klim = ((j == itemlen-1) ? nglyphs : log_clusters[j+1]); - ng = klim - log_clusters[j]; - g_print ("%d: %d glyphs: ", - charix, ng); - for (k = log_clusters[j]; k < klim; k++) - { - g_print ("%d", iglyphs[k]); - if (k != klim - 1) - g_print (","); - } - clusterix++; - g_print ("\n"); - } - } - } - } -} - -#endif /* BASIC_WIN32_DEBUGGING */ - -static void -set_up_pango_log_clusters (wchar_t *wtext, - gboolean rtl, - int itemlen, - WORD *usp_log_clusters, - int nglyphs, - gint *pango_log_clusters, - int char_offset) -{ - int j, k; - int first_char_in_cluster; - - if (rtl) - { - /* RTL. Walk Uniscribe log_clusters array backwards, build Pango - * log_clusters array forwards. - */ - int glyph0 = 0; - first_char_in_cluster = itemlen - 1; - for (j = itemlen - 1; j >= 0; j--) - { - if (j < itemlen - 1 && usp_log_clusters[j+1] != usp_log_clusters[j]) - { - /* Cluster starts */ - first_char_in_cluster = j; - } - if (j == 0) - { - /* First char, cluster ends */ - for (k = glyph0; k < nglyphs; k++) - pango_log_clusters[k] = first_char_in_cluster + char_offset; - } - else if (usp_log_clusters[j-1] == usp_log_clusters[j]) - { - /* Cluster continues */ - first_char_in_cluster = j-1; - } - else - { - /* Cluster ends */ - for (k = glyph0; k <= usp_log_clusters[j]; k++) - pango_log_clusters[k] = first_char_in_cluster + char_offset; - glyph0 = usp_log_clusters[j] + 1; - } - } - } - else - { - /* LTR. Walk Uniscribe log_clusters array forwards, build Pango - * log_clusters array also forwards. - */ - first_char_in_cluster = 0; - for (j = 0; j < itemlen; j++) - { - if (j > 0 && usp_log_clusters[j-1] != usp_log_clusters[j]) - { - /* Cluster starts */ - first_char_in_cluster = j; - } - if (j == itemlen - 1) - { - /* Last char, cluster ends */ - for (k = usp_log_clusters[j]; k < nglyphs; k++) - pango_log_clusters[k] = first_char_in_cluster + char_offset; - } - else if (usp_log_clusters[j] == usp_log_clusters[j+1]) - { - /* Cluster continues */ - } - else - { - /* Cluster ends */ - for (k = usp_log_clusters[j]; k < usp_log_clusters[j+1]; k++) - pango_log_clusters[k] = first_char_in_cluster + char_offset; - } - } - } -} - -static void -convert_log_clusters_to_byte_offsets (const char *text, - gint length, - PangoGlyphString *glyphs, - gint utf16_len) -{ - const char *p; - int charix, glyphix; - int *byte_offset = g_new (int, utf16_len); - - p = text; - charix = 0; - while (p < text + length) - { - byte_offset[charix] = p - text; - charix++; - if (g_utf8_get_char (p) > 0xFFFF) - { - byte_offset[charix] = p - text; - charix++; - } - p = g_utf8_next_char (p); - } - g_assert (charix <= utf16_len); - - /* Convert utf16 indexes in the log_clusters array to byte offsets. - */ - for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) - { - g_assert (glyphs->log_clusters[glyphix] < utf16_len); - glyphs->log_clusters[glyphix] = byte_offset[glyphs->log_clusters[glyphix]]; - } - - g_free (byte_offset); -} - -typedef struct { - HFONT hfont; - gint32 script; -} script_cache_key; - -static guint -script_cache_key_hash_func (script_cache_key *key) -{ - return g_direct_hash (key->hfont) ^ g_int_hash (&(key->script)); -} - -static gboolean -script_cache_key_equal_func (script_cache_key *a, - script_cache_key *b) -{ - return (a->hfont == b->hfont) && (a->script == b->script); -} - -static gboolean -itemize_shape_and_place (PangoFont *font, - HDC hdc, - wchar_t *wtext, - int wlen, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs) -{ - int i; - int item, nitems, item_step; - int itemlen, glyphix, nglyphs; - SCRIPT_CONTROL control; - SCRIPT_STATE state; - SCRIPT_ITEM items[100]; - double scale = pango_win32_font_get_metrics_factor (font); - HFONT hfont = _pango_win32_font_get_hfont (font); - static GHashTable *script_cache_hash = NULL; - - if (!script_cache_hash) - script_cache_hash = g_hash_table_new ((GHashFunc)script_cache_key_hash_func, - (GEqualFunc)script_cache_key_equal_func); - - memset (&control, 0, sizeof (control)); - memset (&state, 0, sizeof (state)); - - control.uDefaultLanguage = make_langid (analysis->language); - state.uBidiLevel = analysis->level; - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print (G_STRLOC ": ScriptItemize: uDefaultLanguage:%04x uBidiLevel:%d\n", - control.uDefaultLanguage, state.uBidiLevel); -#endif - if (ScriptItemize (wtext, wlen, G_N_ELEMENTS (items), &control, NULL, - items, &nitems)) - { -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print ("ScriptItemize failed\n"); -#endif - return FALSE; - } - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print ("%d items:\n", nitems); -#endif - - if (analysis->level % 2) - { - item = nitems - 1; - item_step = -1; - } - else - { - item = 0; - item_step = 1; - } - - for (i = 0; i < nitems; i++, item += item_step) - { - WORD iglyphs[1000]; - WORD log_clusters[1000]; - SCRIPT_VISATTR visattrs[1000]; - int advances[1000]; - GOFFSET offsets[1000]; - ABC abc; - gint32 script = items[item].a.eScript; - int ng; - int char_offset; - SCRIPT_CACHE *script_cache; - script_cache_key font_and_script_key; - - memset (advances, 0, sizeof (advances)); - memset (offsets, 0, sizeof (offsets)); - memset (&abc, 0, sizeof (abc)); - - /* Note that itemlen is number of wchar_t's i.e. surrogate pairs - * count as two! - */ - itemlen = items[item+1].iCharPos - items[item].iCharPos; - char_offset = items[item].iCharPos; - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - { - static const SCRIPT_PROPERTIES **scripts; - static int nscripts; - if (!nscripts) - ScriptGetProperties (&scripts, &nscripts); - g_print (" Item %d: iCharPos=%d eScript=%d (%s) %s%s%s%s%s%s%s wchar_t %d--%d (%d)\n", - item, items[item].iCharPos, script, - lang_name (scripts[script]->langid), - scripts[script]->fComplex ? "complex" : "simple", - items[item].a.fRTL ? " fRTL" : "", - items[item].a.fLayoutRTL ? " fLayoutRTL" : "", - items[item].a.fLinkBefore ? " fLinkBefore" : "", - items[item].a.fLinkAfter ? " fLinkAfter" : "", - items[item].a.fLogicalOrder ? " fLogicalOrder" : "", - items[item].a.fNoGlyphIndex ? " fNoGlyphIndex" : "", - items[item].iCharPos, items[item+1].iCharPos-1, itemlen); -#endif - /* Create a hash key based on hfont and script engine */ - font_and_script_key.hfont = hfont; - font_and_script_key.script = script; - - /* Get the script cache for this hfont and script */ - script_cache = g_hash_table_lookup (script_cache_hash, &font_and_script_key); - if (!script_cache) - { - script_cache_key *key_n; - SCRIPT_CACHE *new_script_cache; - - key_n = g_new (script_cache_key, 1); - *key_n = font_and_script_key; - - new_script_cache = g_new0 (SCRIPT_CACHE, 1); - script_cache = new_script_cache; - - /* Insert the new value */ - g_hash_table_insert (script_cache_hash, key_n, new_script_cache); - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print (" New SCRIPT_CACHE for font %p and script %d\n", hfont, script); -#endif - } - - items[item].a.fRTL = analysis->level % 2; - if (ScriptShape (hdc, script_cache, - wtext + items[item].iCharPos, itemlen, - G_N_ELEMENTS (iglyphs), - &items[item].a, - iglyphs, - log_clusters, - visattrs, - &nglyphs)) - { -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print ("pangowin32-shape: ScriptShape failed\n"); -#endif - return FALSE; - } - -#ifdef BASIC_WIN32_DEBUGGING - dump_glyphs_and_log_clusters (items[item].a.fRTL, itemlen, - items[item].iCharPos, log_clusters, - iglyphs, nglyphs); -#endif - - ng = glyphs->num_glyphs; - pango_glyph_string_set_size (glyphs, ng + nglyphs); - - set_up_pango_log_clusters (wtext + items[item].iCharPos, - items[item].a.fRTL, itemlen, log_clusters, - nglyphs, glyphs->log_clusters + ng, - char_offset); - - if (ScriptPlace (hdc, script_cache, iglyphs, nglyphs, - visattrs, &items[item].a, - advances, offsets, &abc)) - { -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print ("pangowin32-shape: ScriptPlace failed\n"); -#endif - return FALSE; - } - - for (glyphix = 0; glyphix < nglyphs; glyphix++) - { - if (iglyphs[glyphix] != 0) - { - glyphs->glyphs[ng+glyphix].glyph = iglyphs[glyphix]; - glyphs->glyphs[ng+glyphix].geometry.width = floor (0.5 + scale * advances[glyphix]); - glyphs->glyphs[ng+glyphix].geometry.x_offset = floor (0.5 + scale * offsets[glyphix].du); - glyphs->glyphs[ng+glyphix].geometry.y_offset = -floor (0.5 + scale * offsets[glyphix].dv); - } - else - { - PangoRectangle logical_rect; - /* Should pass actual char that was not found to - * PANGO_GET_UNKNOWN_GLYPH(), but a bit hard to - * find out that at this point, so cheat and use 0. - */ - PangoGlyph unk = PANGO_GET_UNKNOWN_GLYPH (0); - - glyphs->glyphs[ng+glyphix].glyph = unk; - pango_font_get_glyph_extents (font, unk, NULL, &logical_rect); - glyphs->glyphs[ng+glyphix].geometry.width = logical_rect.width; - glyphs->glyphs[ng+glyphix].geometry.x_offset = 0; - glyphs->glyphs[ng+glyphix].geometry.y_offset = 0; - } - } - } - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - { - g_print (" Pango log_clusters (level:%d), char index:", analysis->level); - for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) - g_print ("%d ", glyphs->log_clusters[glyphix]); - g_print ("\n"); - } -#endif - - return TRUE; -} - -static gboolean -uniscribe_shape (PangoFont *font, - const char *text, - gint length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs) -{ - wchar_t *wtext; - long wlen; - HDC hdc = _pango_win32_hdc; - gboolean retval = TRUE; - - if (!pango_win32_font_select_font (font, hdc)) - return FALSE; - - wtext = g_utf8_to_utf16 (text, length, NULL, &wlen, NULL); - if (wtext == NULL) - retval = FALSE; - - if (retval) - { - retval = itemize_shape_and_place (font, hdc, wtext, wlen, analysis, glyphs); - } - - if (retval) - { - convert_log_clusters_to_byte_offsets (text, length, glyphs, wlen); -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - { - int glyphix; - - g_print (" Pango log_clusters, byte offsets:"); - for (glyphix = 0; glyphix < glyphs->num_glyphs; glyphix++) - g_print ("%d ", glyphs->log_clusters[glyphix]); - g_print ("\n"); - } -#endif - } - - pango_win32_font_done_font (font); - - g_free (wtext); - - return retval && glyphs->num_glyphs > 0; -} - -static gboolean -text_is_simple (const char *text, - gint length) -{ - gboolean retval; - wchar_t *wtext; - long wlen; - - wtext = (wchar_t *) g_utf8_to_utf16 (text, length, NULL, &wlen, NULL); - if (wtext == NULL) - return TRUE; - - retval = (ScriptIsComplex (wtext, wlen, SIC_COMPLEX) == S_FALSE); - - g_free (wtext); - -#ifdef BASIC_WIN32_DEBUGGING - if (pango_win32_debug) - g_print ("text_is_simple: %.*s (%ld wchar_t): %s\n", - MIN (length, 10), text, wlen, retval ? "YES" : "NO"); -#endif - - return retval; -} - -void -_pango_win32_shape (PangoFont *font, - const char *text, - unsigned int length, - const PangoAnalysis *analysis, - PangoGlyphString *glyphs, - const char *paragraph_text G_GNUC_UNUSED, - unsigned int paragraph_length G_GNUC_UNUSED) -{ - int n_chars; - int i; - const char *p; - - g_return_if_fail (font != NULL); - g_return_if_fail (text != NULL); - g_return_if_fail (length >= 0); - g_return_if_fail (analysis != NULL); - - if (!text_is_simple (text, length) && - uniscribe_shape (font, text, length, analysis, glyphs)) - return; - - n_chars = pango_utf8_strlen (text, length); - - pango_glyph_string_set_size (glyphs, n_chars); - - p = text; - for (i = 0; i < n_chars; i++) - { - gunichar wc; - gunichar mirrored_ch; - PangoGlyph index; - - wc = g_utf8_get_char (p); - - if (analysis->level % 2) - if (g_unichar_get_mirror_char (wc, &mirrored_ch)) - wc = mirrored_ch; - - if (wc == 0xa0) /* non-break-space */ - wc = 0x20; - - if (pango_is_zero_width (wc)) - { - set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY); - } - else - { - index = find_char (font, wc); - if (index) - { - set_glyph (font, glyphs, i, p - text, index); - - if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK) - { - if (i > 0) - { - PangoRectangle logical_rect, ink_rect; - - glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width, - glyphs->glyphs[i].geometry.width); - glyphs->glyphs[i-1].geometry.width = 0; - glyphs->log_clusters[i] = glyphs->log_clusters[i-1]; - - /* Some heuristics to try to guess how overstrike glyphs are - * done and compensate - */ - /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */ - pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect); - if (logical_rect.width == 0 && ink_rect.x == 0) - glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2; - } - } - } - else - set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc)); - } - - p = g_utf8_next_char (p); - } - - /* Simple bidi support... may have separate modules later */ - - if (analysis->level % 2) - { - int start, end; - - /* Swap all glyphs */ - swap_range (glyphs, 0, n_chars); - - /* Now reorder glyphs within each cluster back to LTR */ - for (start = 0; start < n_chars;) - { - end = start; - while (end < n_chars && - glyphs->log_clusters[end] == glyphs->log_clusters[start]) - end++; - - swap_range (glyphs, start, end); - start = end; - } - } -} |