Re: Adding any new Pango engines...



Hi Owen, Pablo,

Finally, I found where the problem was.
It's in macro "is_composible" which was refered to "char_class" variable which
wasn't declared.

Attached is the fix one.

I think I'll take a couple days to test it and, at least, the hebrew case
is still working like before, I'm going to put it back to CVS.

Thanks,

Chookij V.

] Date: Fri, 13 Apr 2001 15:34:46 -0400
] From: Owen Taylor <otaylor redhat com>
] Subject: Re: Adding any new Pango engines...
] To: gtk-i18n-list gnome org
] Cc: Chookij Vanatham <Chookij Vanatham Eng Sun COM>
] MIME-version: 1.0
] User-Agent: Gnus/5.0807 (Gnus v5.8.7) Emacs/20.7
] 
] 
] Chookij Vanatham <chookij mpkmail Eng Sun COM> writes:
] 
] > Hi,
] > 
] > I'm trying to add another new Pango engine but I've got the following error
] > by running "pango/pango/pango-querymodules".
] > 
] > % ./pango-querymodules
] > ...
] > ...
] > Cannot load module 
/home/chookij/GNOME2.0/lib/pango/modules/pango-hebrew-x.so: 
] > couldn't open libtool archive
] > /home/chookij/GNOME2.0/lib/pango/modules/pango-hebrew-x.so does not export 
Pango 
] > module API
] > 
] > If anybody has the clue, please let me know.
] 
] I don't see anything obviously wrong with your code or makefiles. What
] symbols are exported from the .so file? (You probably can check that
] with 'nm')
] 
] Regards,
]                                         Owen
] 
/* Pango
 * hebrew-x.c:
 *
 * Copyright (C) 1999 Red Hat Software
 * Author: Owen Taylor <otaylor redhat com>
 *
 * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
 * Author: Chookij Vanatham <Chookij Vanatham Eng Sun 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 <string.h>

#include <glib.h>
#include <string.h>
#include "pangox.h"
#include "pango-engine.h"

#define ucs2iso8859_8(wc)		(unsigned int)((unsigned int)(wc) - 0x0590 + 0x20)
#define iso8859_8_2uni(c)		((gunichar)(c) - 0x20 + 0x0590)

#define MAX_CLUSTER_CHRS	256
#define MAX_GLYPHS		256

/* Define Hebrew character classes */
#define _ND			0
#define _LT			1
#define	_LD			(1<<1)	/* Bet, Kaf, Shin */
#define _YD			(1<<2)
#define _VA			(1<<3)
#define _DA			(1<<4)
#define _PT			(1<<5)
#define	_HO			(1<<6)
#define	_12			(1<<7)

#define NormalLetter		_LT
#define	BetKafShinLetter	_LD
#define YODLetter		_YD
#define VAVLetter		_VA
#define DAGESHPoint		_DA
#define	OtherPoint		_PT
#define	HolamPoint		_HO
#define	OneTwoPoint		_12

#define is_char_type(wc, mask)	(char_type_table[ucs2iso8859_8 ((wc))] & (mask))
#define	is_composible(cur_wc, nxt_wc)	(compose_table[char_type_table[ucs2iso8859_8 (cur_wc)]]\
						      [char_type_table[ucs2iso8859_8 (nxt_wc)]])

#define SCRIPT_ENGINE_NAME "HebrewScriptEngineX"

/* We handle the range U+0591 to U+05f4 exactly
 */
static PangoEngineRange hebrew_ranges[] = {
  { 0x0591, 0x05f4, "*" },  /* Hebrew */
};

static PangoEngineInfo script_engines[] = {
  {
    SCRIPT_ENGINE_NAME,
    PANGO_ENGINE_TYPE_SHAPE,
    PANGO_RENDER_TYPE_X,
    hebrew_ranges, G_N_ELEMENTS(hebrew_ranges)
  }
};

/*
 * X window system script engine portion
 */

typedef struct _HebrewFontInfo HebrewFontInfo;

/* The type of encoding that we will use
 */
typedef enum {
  HEBREW_FONT_NONE,
  HEBREW_FONT_ISO8859_8,
  HEBREW_FONT_ISO10646
} HebrewFontType;

struct _HebrewFontInfo
{
  PangoFont   *font;
  HebrewFontType type;
  PangoXSubfont subfont;
};

static const gint char_type_table[128] = {
  /*       0,   1,   2,   3,   4,   5,   6,   7 */

  /*00*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
  /*10*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
		
  /*20*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
  /*30*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
  /*40*/ _PT, _PT, _PT, _PT, _12, _12, _PT, _PT,
         _PT, _HO, _ND, _PT, _DA, _ND, _ND, _ND,
  /*50*/ _ND, _PT, _PT, _ND, _PT, _ND, _ND, _ND,
         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
  /*60*/ _LT, _LT, _LT, _LT, _LT, _VA, _LT, _LT,
         _LT, _YD, _LT, _LT, _LT, _LT, _LT, _LT,
  /*70*/ _LT, _LT, _LT, _LT, _LT, _LT, _LT, _LT,
         _LT, _LT, _LT, _ND, _ND, _ND, _ND, _ND,
};

static const gboolean compose_table[9][9] = {
      /* Cn */ /*     0,     1,     2,     3,     4,     5,     6,     7,     8 */
/* Cn-1 00 */	{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
  /* 10 */      { FALSE, FALSE, FALSE,  TRUE,  TRUE, FALSE,  TRUE, FALSE,  TRUE },
  /* 20 */      { FALSE, FALSE, FALSE,  TRUE,  TRUE,  TRUE,  TRUE, FALSE,  TRUE },
  /* 30 */      { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
  /* 40 */      { FALSE, FALSE, FALSE, FALSE, FALSE,  TRUE, FALSE,  TRUE, FALSE },
  /* 50 */      { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
  /* 60 */      { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
  /* 70 */	{ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE },
  /* 80 */	{ FALSE, FALSE, FALSE,  TRUE, FALSE, FALSE, FALSE, FALSE, FALSE }
};

/* Sun Hebrew Font Layout
 */
static const gint Sun_shape_table[128] = {
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,

  0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
  0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
  0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
  0xF8, 0xF9, 0xFA, 0x00,  0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
};

/* Unicode Hebrew Font Layout
 */
static const gint Unicode_shape_table[128] = {
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,

  0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
  0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
  0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x0000, 0x0000, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,

  0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
  0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
  0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
  0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,

  0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x0000, 0x0000, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};

/* Returns a structure with information we will use to rendering given the
 * #PangoFont. This is computed once per font and cached for later retrieval.
 */
static HebrewFontInfo *
get_font_info (PangoFont *font)
{
  static const char *charsets[] = {
    "iso8859-8",
    "iso10646-1",
  };

  static const int charset_types[] = {
    HEBREW_FONT_ISO8859_8,
    HEBREW_FONT_ISO10646,
  };
  
  HebrewFontInfo *font_info;
  GQuark info_id = g_quark_from_string ("hebrew-font-info");
  
  font_info = g_object_get_qdata (G_OBJECT (font), info_id);

  if (!font_info)
    {
      /* No cached information not found, so we need to compute it
       * from scratch
       */
      PangoXSubfont *subfont_ids;
      gint *subfont_charsets;
      gint n_subfonts, i;

      font_info = g_new (HebrewFontInfo, 1);
      font_info->font = font;
      font_info->type = HEBREW_FONT_NONE;
      
      g_object_set_qdata_full (G_OBJECT (font), info_id, font_info, (GDestroyNotify)g_free);
      
      n_subfonts = pango_x_list_subfonts (font, (char **)charsets, G_N_ELEMENTS (charsets),
					  &subfont_ids, &subfont_charsets);

      for (i=0; i < n_subfonts; i++)
	{
	  HebrewFontType font_type = charset_types[subfont_charsets[i]];
	  
	  if (font_type == HEBREW_FONT_ISO10646 &&
	      pango_x_has_glyph (font, PANGO_X_MAKE_GLYPH (subfont_ids[i], 0x05D0)))
	    {
	      font_info->type = font_type;
	      font_info->subfont = subfont_ids[i];
	      
	      break;
	    }
	  else if (font_type == HEBREW_FONT_ISO8859_8 &&
		   pango_x_has_glyph (font, PANGO_X_MAKE_GLYPH (subfont_ids[i], 0xE0)))
	    {
	      font_info->type = font_type;
	      font_info->subfont = subfont_ids[i];
	      
	      break;
	    }
	}

      g_free (subfont_ids);
      g_free (subfont_charsets);
    }

  return font_info;
}

static void
add_glyph (HebrewFontInfo   *font_info, 
	   PangoGlyphString *glyphs, 
	   gint              cluster_start, 
	   PangoGlyph        glyph,
	   gboolean          combining)
{
  PangoRectangle ink_rect, logical_rect;
  gint index = glyphs->num_glyphs;

  pango_glyph_string_set_size (glyphs, index + 1);
  
  glyphs->glyphs[index].glyph = glyph;
  glyphs->glyphs[index].attr.is_cluster_start = combining ? 0 : 1;
  
  glyphs->log_clusters[index] = cluster_start;

  pango_font_get_glyph_extents (font_info->font,
				glyphs->glyphs[index].glyph, &ink_rect, &logical_rect);

  if (combining)
    {
      if ((font_info->type == HEBREW_FONT_ISO8859_8) ||
	  (font_info->type == HEBREW_FONT_ISO10646))
	{
          glyphs->glyphs[index].geometry.width =
		logical_rect.width + glyphs->glyphs[index - 1].geometry.width;
          if (logical_rect.width > 0)
	      glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index - 1].geometry.width;
          else
	      glyphs->glyphs[index].geometry.x_offset = glyphs->glyphs[index].geometry.width;
	  glyphs->glyphs[index - 1].geometry.width = 0;
	}
      else
        {
	  glyphs->glyphs[index].geometry.width =
		MAX (logical_rect.width, glyphs->glyphs[index - 1].geometry.width);
	  glyphs->glyphs[index - 1].geometry.width = 0;
	  glyphs->glyphs[index].geometry.x_offset = 0;
        }
    }
  else
    {
      glyphs->glyphs[index].geometry.x_offset = 0;
      glyphs->glyphs[index].geometry.width = logical_rect.width;
    }
  
  glyphs->glyphs[index].geometry.y_offset = 0;
}

static gint
get_adjusted_glyphs_list (HebrewFontInfo *font_info,
			  gunichar *cluster,
			  gint num_chrs,
			  PangoGlyph *glyph_lists,
			  const gint *shaping_table)
{
  gint i = 0;

  if ((num_chrs == 1) &&
      is_char_type (cluster[0], DAGESHPoint|OtherPoint|HolamPoint|OneTwoPoint))
    {
      glyph_lists[0] = PANGO_X_MAKE_GLYPH (font_info->subfont, 0x20);
      glyph_lists[1] = PANGO_X_MAKE_GLYPH (font_info->subfont,
			shaping_table[ucs2iso8859_8 (cluster[0])]);
      return 2;
    }
  else
    {
      while (i < num_chrs) {
	glyph_lists[i] = PANGO_X_MAKE_GLYPH (font_info->subfont,
				shaping_table[ucs2iso8859_8 (cluster[i])]);
	i++;
      }
      return num_chrs;
    }
}

static gint
get_glyphs_list (HebrewFontInfo	*font_info,
		 gunichar	*cluster,
		 gint		num_chrs,
		 PangoGlyph	*glyph_lists)
{
  gint i;

  switch (font_info->type)
    {
      case HEBREW_FONT_NONE:
        for (i=0; i < num_chrs; i++)
	  glyph_lists[i] = pango_x_get_unknown_glyph (font_info->font);
        return num_chrs;

      case HEBREW_FONT_ISO8859_8:
        return get_adjusted_glyphs_list (font_info, cluster,
			num_chrs, glyph_lists, Sun_shape_table);
      
      case HEBREW_FONT_ISO10646:
        return get_adjusted_glyphs_list (font_info, cluster,
			num_chrs, glyph_lists, Unicode_shape_table);
    }
  return 0;
}

static void
add_cluster (HebrewFontInfo	*font_info,
	     PangoGlyphString	*glyphs,
	     gint		cluster_start,
	     gunichar		*cluster,
	     gint		num_chrs)
	     
{
  PangoGlyph glyphs_list[MAX_GLYPHS];
  gint num_glyphs;
  gint i;
  
  num_glyphs = get_glyphs_list(font_info, cluster, num_chrs, glyphs_list);
  for (i=0; i<num_glyphs; i++)
       add_glyph (font_info, glyphs, cluster_start, glyphs_list[i],
	    		i == 0 ? FALSE : TRUE);
}

static const char *
get_next_cluster(const char	*text,
		 gint		length,
		 gunichar       *cluster,
		 gint		*num_chrs)
{  
  const char *p;
  gint n_chars = 0;
  
  p = text;
  while (p < text + length && n_chars < 3)  
    {
      gunichar current = g_utf8_get_char (p);
      
      if (n_chars == 0 ||
	  is_composible ((gunichar)(cluster[n_chars - 1]), current))
	{
	  cluster[n_chars++] = current;
	  p = g_utf8_next_char (p);
	}
      else
	break;
    }

  *num_chrs = n_chars;
  return p;
}

static void 
hebrew_engine_shape (PangoFont      *font,
		   const char       *text,
		   gint              length,
		   PangoAnalysis    *analysis,
		   PangoGlyphString *glyphs)
{
  HebrewFontInfo *font_info;
  const char *p;
  const char *log_cluster;
  gunichar cluster[MAX_CLUSTER_CHRS];
  gint num_chrs;

  pango_glyph_string_set_size (glyphs, 0);

  font_info = get_font_info (font);

  p = text;
  while (p < text + length)
    {
	log_cluster = p;
	p = get_next_cluster (p, text + length - p, cluster, &num_chrs);
	add_cluster (font_info, glyphs, log_cluster - text, cluster, num_chrs);
    }
}

static PangoCoverage *
hebrew_engine_get_coverage (PangoFont *font,
			   const char *lang)
{
  PangoCoverage *result = pango_coverage_new ();
  
  HebrewFontInfo *font_info = get_font_info (font);
  
  if (font_info->type != HEBREW_FONT_NONE)
    {
      gunichar wc;
      
      for (wc = 0x590; wc <= 0x5f4; wc++)
	pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
    }

  return result;
}

static PangoEngine *
hebrew_engine_x_new ()
{
  PangoEngineShape *result;
  
  result = g_new (PangoEngineShape, 1);

  result->engine.id = SCRIPT_ENGINE_NAME;
  result->engine.type = PANGO_ENGINE_TYPE_SHAPE;
  result->engine.length = sizeof (result);
  result->script_shape = hebrew_engine_shape;
  result->get_coverage = hebrew_engine_get_coverage;

  return (PangoEngine *)result;
}

/* The following three functions provide the public module API for
 * Pango. If we are compiling it is a module, then we name the
 * entry points script_engine_list, etc. But if we are compiling
 * it for inclusion directly in Pango, then we need them to
 * to have distinct names for this module, so we prepend
 * _pango_hebrew_x_
 */
#ifdef X_MODULE_PREFIX
#define MODULE_ENTRY(func) _pango_hebrew_x_##func
#else
#define MODULE_ENTRY(func) func
#endif

/* List the engines contained within this module
 */
void 
MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines)
{
  *engines = script_engines;
  *n_engines = G_N_ELEMENTS (script_engines);
}

/* Load a particular engine given the ID for the engine
 */
PangoEngine *
MODULE_ENTRY(script_engine_load) (const char *id)
{
  if (!strcmp (id, SCRIPT_ENGINE_NAME))
    return hebrew_engine_x_new ();
  else
    return NULL;
}

void 
MODULE_ENTRY(script_engine_unload) (PangoEngine *engine)
{
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]