summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2014-07-27 18:11:16 -0400
committerBehdad Esfahbod <behdad@behdad.org>2015-04-04 16:13:07 -0700
commit14c11dd96e1547aaede1bb05a0243f5b0b53186e (patch)
treed9af93737a52e46e8f9b27eefc86918aed30e4a6 /modules
parentcfe9ce995d7e12a3e3f64c923123337d5dba25b0 (diff)
downloadpango-14c11dd96e1547aaede1bb05a0243f5b0b53186e.tar.gz
Move shapers from modules/basic/ into pango/
Note wired up yet. Doesn't build.
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile.am1
-rw-r--r--modules/basic/Makefile.am36
-rw-r--r--modules/basic/basic-coretext.c547
-rw-r--r--modules/basic/basic-fc.c483
-rw-r--r--modules/basic/basic-win32.c877
5 files changed, 0 insertions, 1944 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am
index be8e285e..fa58389e 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -2,7 +2,6 @@
SUBDIRS = \
arabic \
- basic \
indic \
thai
diff --git a/modules/basic/Makefile.am b/modules/basic/Makefile.am
deleted file mode 100644
index 22d657b2..00000000
--- a/modules/basic/Makefile.am
+++ /dev/null
@@ -1,36 +0,0 @@
-INCLUDES = \
- -DG_LOG_DOMAIN=\"Pango\" \
- -DPANGO_ENABLE_ENGINE \
- $(PANGO_DEBUG_FLAGS) \
- -I$(top_srcdir) \
- -I$(top_srcdir)/pango \
- $(GLIB_CFLAGS)
-
-noinst_LTLIBRARIES =
-
-if HAVE_FREETYPE
-INCLUDES += $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS)
-noinst_LTLIBRARIES += libpango-basic-fc.la
-endif
-
-libpango_basic_fc_la_SOURCES = basic-fc.c
-libpango_basic_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_fc
-
-
-if HAVE_WIN32
-noinst_LTLIBRARIES += libpango-basic-win32.la
-endif
-
-libpango_basic_win32_la_LIBADD = -lgdi32 -lusp10
-libpango_basic_win32_la_SOURCES = basic-win32.c
-libpango_basic_win32_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_win32
-
-if HAVE_CORE_TEXT
-INCLUDES += $(CAIRO_CFLAGS)
-noinst_LTLIBRARIES += libpango-basic-coretext.la
-endif
-
-libpango_basic_coretext_la_SOURCES = basic-coretext.c
-libpango_basic_coretext_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_basic_coretext
-
--include $(top_srcdir)/git.mk
diff --git a/modules/basic/basic-coretext.c b/modules/basic/basic-coretext.c
deleted file mode 100644
index 0e966cd9..00000000
--- a/modules/basic/basic-coretext.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/* Pango
- * basic-coretext.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-engine.h"
-#include "pango-utils.h"
-#include "pango-fontmap.h"
-#include "pangocoretext.h"
-#include "pango-impl-utils.h"
-
-/* No extra fields needed */
-typedef PangoEngineShape BasicEngineCoreText;
-typedef PangoEngineShapeClass BasicEngineCoreTextClass ;
-
-#define SCRIPT_ENGINE_NAME "BasicScriptEngineCoreText"
-#define RENDER_TYPE PANGO_RENDER_TYPE_CORE_TEXT
-
-static PangoEngineScriptInfo basic_scripts[] = {
- { PANGO_SCRIPT_COMMON, "" }
-};
-
-static PangoEngineInfo script_engines[] = {
- {
- SCRIPT_ENGINE_NAME,
- PANGO_ENGINE_TYPE_SHAPE,
- RENDER_TYPE,
- basic_scripts, G_N_ELEMENTS(basic_scripts)
- }
-};
-
-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 shaping engine 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 shaping
- * engine function easier.
- */
-
-struct RunIterator
-{
- CTLineRef line;
- CFStringRef cstr;
- CFArrayRef runs;
- CFIndex glyph_count;
-
- CFIndex total_ct_i;
- CFIndex ct_i;
-
- 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;
-}
-
-/* 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
- * basic_engine_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)
-{
- return CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]);
-}
-
-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->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->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->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);
-
- 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;
-}
-
-
-static void
-basic_engine_shape (PangoEngineShape *engine,
- 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:
- * # CoreText strings are UTF16, and the indices *often* refer to characters,
- * but not *always*. Notable exception is when a character is encoded using
- * two UTF16 code points. This are two characters in a CFString. At this point
- * advancing a single character in the CFString and advancing a single character
- * using g_utf8_next_char in the const char string goes out of sync.
- * # 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;
-
- /* Translate the glyph list to a PangoGlyphString */
- n_chars = g_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);
-
- 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)
- {
- /* gs_i is behind, insert empty glyph */
- set_glyph (font, glyphs, gs_i, p - text, PANGO_GLYPH_EMPTY);
- continue;
- }
- else if (gi->index < gs_i)
- {
- 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);
-}
-
-static void
-basic_engine_core_text_class_init (PangoEngineShapeClass *class)
-{
- class->script_shape = basic_engine_shape;
-}
-
-PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineCoreText, basic_engine_core_text,
- basic_engine_core_text_class_init, NULL);
-
-void
-PANGO_MODULE_ENTRY(init) (GTypeModule *module)
-{
- basic_engine_core_text_register_type (module);
-}
-
-void
-PANGO_MODULE_ENTRY(exit) (void)
-{
-}
-
-void
-PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
- int *n_engines)
-{
- *engines = script_engines;
- *n_engines = G_N_ELEMENTS (script_engines);
-}
-
-PangoEngine *
-PANGO_MODULE_ENTRY(create) (const char *id)
-{
- if (!strcmp (id, SCRIPT_ENGINE_NAME))
- return g_object_new (basic_engine_core_text_type, NULL);
- else
- return NULL;
-}
-
diff --git a/modules/basic/basic-fc.c b/modules/basic/basic-fc.c
deleted file mode 100644
index d77dacef..00000000
--- a/modules/basic/basic-fc.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/* Pango
- * basic-fc.c: Basic shaper for FreeType-based backends
- *
- * Copyright (C) 2000, 2007, 2009 Red Hat Software
- * Authors:
- * Owen Taylor <otaylor@redhat.com>
- * Behdad Esfahbod <behdad@behdad.org>
- *
- * 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 <string.h>
-
-#define PANGO_ENABLE_BACKEND 1 /* XXX */
-
-#include "pango-engine.h"
-#include "pango-utils.h"
-#include "pangofc-fontmap.h"
-#include "pangofc-font.h"
-#include <hb-ft.h>
-#include <hb-glib.h>
-
-#define PANGO_UNITS_26_6(d) ((d) << 4)
-
-
-/* No extra fields needed */
-typedef PangoEngineShape BasicEngineFc;
-typedef PangoEngineShapeClass BasicEngineFcClass;
-
-#define SCRIPT_ENGINE_NAME "BasicScriptEngineFc"
-#define RENDER_TYPE PANGO_RENDER_TYPE_FC
-
-static PangoEngineScriptInfo basic_scripts[] = {
- { PANGO_SCRIPT_COMMON, "" }
-};
-
-static PangoEngineInfo script_engines[] = {
- {
- SCRIPT_ENGINE_NAME,
- PANGO_ENGINE_TYPE_SHAPE,
- RENDER_TYPE,
- basic_scripts, G_N_ELEMENTS(basic_scripts)
- }
-};
-
-
-/* cache a single hb_buffer_t */
-static hb_buffer_t *cached_buffer = NULL; /* MT-safe */
-G_LOCK_DEFINE_STATIC (cached_buffer);
-
-static hb_buffer_t *
-create_buffer (void)
-{
- hb_buffer_t *buffer;
-
- buffer = hb_buffer_create ();
- hb_buffer_set_unicode_funcs (buffer, hb_glib_get_unicode_funcs ());
-
- return buffer;
-}
-
-static hb_buffer_t *
-acquire_buffer (gboolean *free_buffer)
-{
- hb_buffer_t *buffer;
-
- if (G_LIKELY (G_TRYLOCK (cached_buffer)))
- {
- if (G_UNLIKELY (!cached_buffer))
- cached_buffer = create_buffer ();
-
- buffer = cached_buffer;
- *free_buffer = FALSE;
- }
- else
- {
- buffer = create_buffer ();
- *free_buffer = TRUE;
- }
-
- return buffer;
-}
-
-static void
-release_buffer (hb_buffer_t *buffer, gboolean free_buffer)
-{
- if (G_LIKELY (!free_buffer))
- {
- hb_buffer_reset (buffer);
- G_UNLOCK (cached_buffer);
- }
- else
- hb_buffer_destroy (buffer);
-}
-
-typedef struct _PangoFcHbContext {
- FT_Face ft_face;
- PangoFcFont *fc_font;
- gboolean vertical;
- int improper_sign;
-} PangoFcHbContext;
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph (hb_font_t *font, void *font_data,
- hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- hb_codepoint_t *glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- PangoFcFont *fc_font = context->fc_font;
-
- *glyph = pango_fc_font_get_glyph (fc_font, unicode);
- if (G_LIKELY (*glyph))
- return TRUE;
-
- *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
-
- /* We draw our own invalid-Unicode shape, so prevent HarfBuzz
- * from using REPLACEMENT CHARACTER. */
- if (unicode > 0x10FFFF)
- return TRUE;
-
- return FALSE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_contour_point (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph, unsigned int point_index,
- hb_position_t *x, hb_position_t *y,
- void *user_data G_GNUC_UNUSED)
-{
- return FALSE;
-#if 0
- FT_Face ft_face = (FT_Face) font_data;
- int load_flags = FT_LOAD_DEFAULT;
-
- /* TODO: load_flags, embolden, etc */
-
- if (HB_UNLIKELY (FT_Load_Glyph (ft_face, glyph, load_flags)))
- return FALSE;
-
- if (HB_UNLIKELY (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
- return FALSE;
-
- if (HB_UNLIKELY (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
- return FALSE;
-
- *x = ft_face->glyph->outline.points[point_index].x;
- *y = ft_face->glyph->outline.points[point_index].y;
-
- return TRUE;
-#endif
-}
-
-static hb_position_t
-pango_fc_hb_font_get_glyph_advance (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- PangoFcFont *fc_font = context->fc_font;
- PangoRectangle logical;
-
- pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, NULL, &logical);
-
- return logical.width;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_extents (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- PangoFcFont *fc_font = context->fc_font;
- PangoRectangle ink;
-
- pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, &ink, NULL);
-
- if (G_LIKELY (!context->vertical)) {
- extents->x_bearing = ink.x;
- extents->y_bearing = ink.y;
- extents->width = ink.width;
- extents->height = ink.height;
- } else {
- /* XXX */
- extents->x_bearing = ink.x;
- extents->y_bearing = ink.y;
- extents->width = ink.height;
- extents->height = ink.width;
- }
-
- return TRUE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_h_origin (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- FT_Face ft_face = context->ft_face;
- int load_flags = FT_LOAD_DEFAULT;
-
- if (!context->vertical) return TRUE;
-
- if (FT_Load_Glyph (ft_face, glyph, load_flags))
- return FALSE;
-
- /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
- * have a Y growing upward. Hence the extra negation. */
- *x = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX);
- *y = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY));
-
- /* XXX */
- *x = -*x;
- *y = *y;
-
- return TRUE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_v_origin (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- FT_Face ft_face = context->ft_face;
- int load_flags = FT_LOAD_DEFAULT;
-
- if (context->vertical) return TRUE;
-
- if (FT_Load_Glyph (ft_face, glyph, load_flags))
- return FALSE;
-
- /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
- * have a Y growing upward. Hence the extra negation. */
- *x = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX);
- *y = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY));
-
- /* XXX */
-
- return TRUE;
-}
-
-
-static hb_position_t
-pango_fc_hb_font_get_h_kerning (hb_font_t *font, void *font_data,
- hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoFcHbContext *context = (PangoFcHbContext *) font_data;
- FT_Face ft_face = context->ft_face;
- FT_Vector kerning;
-
- if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerning))
- return 0;
-
- return PANGO_UNITS_26_6 (kerning.x);
-}
-
-static hb_font_funcs_t *
-pango_fc_get_hb_font_funcs (void)
-{
- static hb_font_funcs_t *funcs;
-
- if (G_UNLIKELY (!funcs)) {
- funcs = hb_font_funcs_create ();
- hb_font_funcs_set_glyph_func (funcs, pango_fc_hb_font_get_glyph, NULL, NULL);
- hb_font_funcs_set_glyph_h_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL);
- hb_font_funcs_set_glyph_v_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL);
- hb_font_funcs_set_glyph_h_origin_func (funcs, pango_fc_hb_font_get_glyph_h_origin, NULL, NULL);
- hb_font_funcs_set_glyph_v_origin_func (funcs, pango_fc_hb_font_get_glyph_v_origin, NULL, NULL);
- hb_font_funcs_set_glyph_h_kerning_func (funcs, pango_fc_hb_font_get_h_kerning, NULL, NULL);
- /* Don't need v_kerning. */
- hb_font_funcs_set_glyph_extents_func (funcs, pango_fc_hb_font_get_glyph_extents, NULL, NULL);
- hb_font_funcs_set_glyph_contour_point_func (funcs, pango_fc_hb_font_get_glyph_contour_point, NULL, NULL);
- /* Don't need glyph_name / glyph_from_name */
- }
-
- return funcs;
-}
-
-
-
-
-static void
-basic_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
- PangoFont *font,
- const char *item_text,
- unsigned int item_length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs,
- const char *paragraph_text,
- unsigned int paragraph_length)
-{
- PangoFcHbContext context;
- PangoFcFont *fc_font;
- FT_Face ft_face;
- hb_face_t *hb_face;
- hb_font_t *hb_font;
- hb_buffer_t *hb_buffer;
- hb_direction_t hb_direction;
- gboolean free_buffer;
- gboolean is_hinted;
- hb_glyph_info_t *hb_glyph;
- hb_glyph_position_t *hb_position;
- int last_cluster;
- guint i, num_glyphs;
- unsigned int item_offset = item_text - paragraph_text;
- hb_feature_t features[8];
- unsigned int num_features = 0;
-
- g_return_if_fail (font != NULL);
- g_return_if_fail (analysis != NULL);
-
- fc_font = PANGO_FC_FONT (font);
- ft_face = pango_fc_font_lock_face (fc_font);
- if (!ft_face)
- return;
-
- /* TODO: Cache hb_font? */
- context.ft_face = ft_face;
- context.fc_font = fc_font;
- context.vertical = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity);
- context.improper_sign = PANGO_GRAVITY_IS_IMPROPER (analysis->gravity) ? -1 : +1;
- hb_face = hb_ft_face_create_cached (ft_face);
- hb_font = hb_font_create (hb_face);
- hb_font_set_funcs (hb_font,
- pango_fc_get_hb_font_funcs (),
- &context,
- NULL);
- hb_font_set_scale (hb_font,
- /* XXX CTM */
- context.improper_sign *
- (((guint64) ft_face->size->metrics.x_scale * ft_face->units_per_EM) >> 12),
- context.improper_sign *
- -(((guint64) ft_face->size->metrics.y_scale * ft_face->units_per_EM) >> 12));
- is_hinted = fc_font->is_hinted;
- hb_font_set_ppem (hb_font,
- is_hinted ? ft_face->size->metrics.x_ppem : 0,
- is_hinted ? ft_face->size->metrics.y_ppem : 0);
-
- hb_buffer = acquire_buffer (&free_buffer);
-
- hb_direction = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity) ? HB_DIRECTION_TTB : HB_DIRECTION_LTR;
- if (analysis->level % 2)
- hb_direction = HB_DIRECTION_REVERSE (hb_direction);
- if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
- hb_direction = HB_DIRECTION_REVERSE (hb_direction);
-
- /* setup buffer */
-
- hb_buffer_set_direction (hb_buffer, hb_direction);
- hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis->script));
- hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis->language), -1));
- hb_buffer_set_flags (hb_buffer,
- (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) |
- (item_offset + item_length == paragraph_length ? HB_BUFFER_FLAG_EOT : 0));
-
- hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
-
- /* Setup features from fontconfig pattern. */
- if (fc_font->font_pattern)
- {
- char *s;
- while (num_features < G_N_ELEMENTS (features) &&
- FcResultMatch == FcPatternGetString (fc_font->font_pattern,
- PANGO_FC_FONT_FEATURES,
- num_features,
- (FcChar8 **) &s))
- {
- gboolean ret = hb_feature_from_string (s, -1, &features[num_features]);
- features[num_features].start = 0;
- features[num_features].end = (unsigned int) -1;
- if (ret)
- num_features++;
- }
- }
-
- hb_shape (hb_font, hb_buffer, features, num_features);
-
- if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
- hb_buffer_reverse (hb_buffer);
-
- /* buffer output */
- num_glyphs = hb_buffer_get_length (hb_buffer);
- hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL);
- pango_glyph_string_set_size (glyphs, num_glyphs);
- last_cluster = -1;
- for (i = 0; i < num_glyphs; i++)
- {
- glyphs->glyphs[i].glyph = hb_glyph->codepoint;
- glyphs->log_clusters[i] = hb_glyph->cluster - item_offset;
- glyphs->glyphs[i].attr.is_cluster_start = glyphs->log_clusters[i] != last_cluster;
- hb_glyph++;
- last_cluster = glyphs->log_clusters[i];
- }
-
- hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL);
- if (context.vertical)
- for (i = 0; i < num_glyphs; i++)
- {
- unsigned int advance = hb_position->y_advance;
- if (is_hinted)
- advance = PANGO_UNITS_ROUND (advance);
- glyphs->glyphs[i].geometry.width = advance;
- /* XXX */
- glyphs->glyphs[i].geometry.x_offset = hb_position->y_offset;
- glyphs->glyphs[i].geometry.y_offset = -hb_position->x_offset;
- hb_position++;
- }
- else /* horizontal */
- for (i = 0; i < num_glyphs; i++)
- {
- unsigned int advance = hb_position->x_advance;
- if (is_hinted)
- advance = PANGO_UNITS_ROUND (advance);
- glyphs->glyphs[i].geometry.width = advance;
- glyphs->glyphs[i].geometry.x_offset = hb_position->x_offset;
- glyphs->glyphs[i].geometry.y_offset = hb_position->y_offset;
- hb_position++;
- }
-
- release_buffer (hb_buffer, free_buffer);
- hb_font_destroy (hb_font);
- hb_face_destroy (hb_face);
- pango_fc_font_unlock_face (fc_font);
-}
-
-static void
-basic_engine_fc_class_init (PangoEngineShapeClass *class)
-{
- class->script_shape = basic_engine_shape;
-}
-
-PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineFc, basic_engine_fc,
- basic_engine_fc_class_init, NULL)
-
-void
-PANGO_MODULE_ENTRY(init) (GTypeModule *module)
-{
- basic_engine_fc_register_type (module);
-}
-
-void
-PANGO_MODULE_ENTRY(exit) (void)
-{
-}
-
-void
-PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
- int *n_engines)
-{
- *engines = script_engines;
- *n_engines = G_N_ELEMENTS (script_engines);
-}
-
-PangoEngine *
-PANGO_MODULE_ENTRY(create) (const char *id)
-{
- if (!strcmp (id, SCRIPT_ENGINE_NAME))
- return g_object_new (basic_engine_fc_type, NULL);
- else
- return NULL;
-}
diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c
deleted file mode 100644
index e9d020da..00000000
--- a/modules/basic/basic-win32.c
+++ /dev/null
@@ -1,877 +0,0 @@
-/* Pango
- * basic-win32.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.h"
-
-extern HFONT _pango_win32_font_get_hfont (PangoFont *font);
-
-#include "pango-engine.h"
-#include "pango-utils.h"
-
-/* No extra fields needed */
-typedef PangoEngineShape BasicEngineWin32;
-typedef PangoEngineShapeClass BasicEngineWin32Class ;
-
-#define SCRIPT_ENGINE_NAME "BasicScriptEngineWin32"
-
-static gboolean pango_win32_debug = FALSE;
-
-#include <usp10.h>
-
-static HDC hdc;
-
-#ifdef BASIC_WIN32_DEBUGGING
-static const SCRIPT_PROPERTIES **scripts;
-static int nscripts;
-#endif
-
-static PangoEngineScriptInfo uniscribe_scripts[] = {
- /* We claim to cover everything ;-) */
- { PANGO_SCRIPT_COMMON, "" },
-};
-
-static PangoEngineScriptInfo basic_scripts[] = {
- /* Those characters that can be rendered legibly without Uniscribe.
- * I am not certain this list is correct.
- */
- { PANGO_SCRIPT_ARMENIAN, "*" },
- { PANGO_SCRIPT_BOPOMOFO, "*" },
- { PANGO_SCRIPT_CHEROKEE, "*" },
- { PANGO_SCRIPT_COPTIC, "*" },
- { PANGO_SCRIPT_CYRILLIC, "*" },
- { PANGO_SCRIPT_DESERET, "*" },
- { PANGO_SCRIPT_ETHIOPIC, "*" },
- { PANGO_SCRIPT_GEORGIAN, "*" },
- { PANGO_SCRIPT_GOTHIC, "*" },
- { PANGO_SCRIPT_GREEK, "*" },
- { PANGO_SCRIPT_HAN, "*" },
- { PANGO_SCRIPT_HANGUL, "*" },
- { PANGO_SCRIPT_HIRAGANA, "*" },
- { PANGO_SCRIPT_KATAKANA, "*" },
- { PANGO_SCRIPT_LATIN, "*" },
- { PANGO_SCRIPT_OGHAM, "*" },
- { PANGO_SCRIPT_OLD_ITALIC, "*" },
- { PANGO_SCRIPT_RUNIC, "*" },
- { PANGO_SCRIPT_THAI, "*" },
- { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
- { PANGO_SCRIPT_YI, "*" },
- { PANGO_SCRIPT_BRAILLE, "*" },
- { PANGO_SCRIPT_CYPRIOT, "*" },
- { PANGO_SCRIPT_LIMBU, "*" },
- { PANGO_SCRIPT_OSMANYA, "*" },
- { PANGO_SCRIPT_SHAVIAN, "*" },
- { PANGO_SCRIPT_LINEAR_B, "*" },
- { PANGO_SCRIPT_UGARITIC, "*" },
-
- /* Claim to handle everything as a fallback */
- { PANGO_SCRIPT_COMMON, "" }
-};
-
-static PangoEngineInfo script_engines[] = {
- {
- SCRIPT_ENGINE_NAME,
- PANGO_ENGINE_TYPE_SHAPE,
- PANGO_RENDER_TYPE_WIN32,
- NULL, 0
- }
-};
-
-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);
-}
-
-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 (g_int64_hash, g_int64_equal);
-
- 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;
- gint64 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)
- 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 = (((gint64) ((gint32) hfont)) << 32) | 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)
- {
- gint64 *key_n;
- SCRIPT_CACHE *new_script_cache;
-
- key_n = g_new (gint64, 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 ("pango-basic-win32: 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 ("pango-basic-win32: 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;
- 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;
-}
-
-static void
-basic_engine_shape (PangoEngineShape *engine,
- 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 = g_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;
- }
- }
-}
-
-static void
-init_uniscribe (void)
-{
-#ifdef BASIC_WIN32_DEBUGGING
- ScriptGetProperties (&scripts, &nscripts);
-#endif
- hdc = pango_win32_get_dc ();
-}
-
-static void
-basic_engine_win32_class_init (PangoEngineShapeClass *class)
-{
- class->script_shape = basic_engine_shape;
-}
-
-PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineWin32, basic_engine_win32,
- basic_engine_win32_class_init, NULL);
-
-void
-PANGO_MODULE_ENTRY(init) (GTypeModule *module)
-{
- init_uniscribe ();
-
- if (pango_win32_get_debug_flag ())
- pango_win32_debug = TRUE;
-
- basic_engine_win32_register_type (module);
-}
-
-void
-PANGO_MODULE_ENTRY(exit) (void)
-{
-}
-
-void
-PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
- int *n_engines)
-{
- init_uniscribe ();
-
- script_engines[0].scripts = basic_scripts;
- script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts);
-
- /* This is stupid, we rewrite the previous two lines. Not
- * going to touch it now. */
- script_engines[0].scripts = uniscribe_scripts;
- script_engines[0].n_scripts = G_N_ELEMENTS (uniscribe_scripts);
-
- *engines = script_engines;
- *n_engines = G_N_ELEMENTS (script_engines);
-}
-
-PangoEngine *
-PANGO_MODULE_ENTRY(create) (const char *id)
-{
- if (!strcmp (id, SCRIPT_ENGINE_NAME))
- return g_object_new (basic_engine_win32_type, NULL);
- else
- return NULL;
-}