You should have received a copy of the GNU Lesser General Public
License along with the m17n library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
02111-1307, USA. */
#include "config.h"
MSymbol Mlayouter;
-static MSymbol McatCf;
-
static MPlist *flt_list;
/* Command ID:
#define GLYPH_CODE_INDEX(code) ((code) - GLYPH_CODE_MIN)
+#define UPDATE_CLUSTER_RANGE(ctx, g) \
+ do { \
+ if ((ctx)->cluster_begin_idx) \
+ { \
+ if (ctx->cluster_begin_pos > (g).pos) \
+ ctx->cluster_begin_pos = (g).pos; \
+ if (ctx->cluster_end_pos < (g).to) \
+ ctx->cluster_end_pos = (g).to; \
+ } \
+ } while (0);
+
enum FontLayoutCmdRuleSrcType
{
SRC_REGEX,
typedef struct
{
+ /* Beginning and end indices of series of SEQ commands. */
+ int seq_beg, seq_end;
+ /* Range of the first character appears in the above series. */
+ int seq_from, seq_to;
+
int n_cmds;
int *cmd_ids;
} FontLayoutCmdCond;
-typedef struct
-{
- MSymbol script;
- MSymbol langsys;
- MSymbol gsub_features;
- MSymbol gpos_features;
-} FontLayoutCmdOTF;
-
enum FontLayoutCmdType
{
FontLayoutCmdTypeRule,
union {
FontLayoutCmdRule rule;
FontLayoutCmdCond cond;
- FontLayoutCmdOTF otf;
+ MFontCapability *otf;
} body;
} FontLayoutCmd;
[FEATURE[,FEATURE]*] | ' ' */
static int
-load_otf_command (FontLayoutCmd *cmd, char *name)
+load_otf_command (FontLayoutCmd *cmd, MSymbol sym)
{
- char *p = name, *beg;
-
- cmd->type = FontLayoutCmdTypeOTF;
- cmd->body.otf.script = cmd->body.otf.langsys = Mnil;
- cmd->body.otf.gsub_features = cmd->body.otf.gpos_features = Mt;
+ char *name = MSYMBOL_NAME (sym);
- while (*p)
+ if (name[0] != ':')
{
- if (*p == ':')
- {
- for (beg = ++p; *p && *p != '/' && *p != '=' && *p != '+'; p++);
- if (beg < p)
- cmd->body.otf.script = msymbol__with_len (beg, p - beg);
- }
- else if (*p == '/')
- {
- for (beg = ++p; *p && *p != '=' && *p != '+'; p++);
- if (beg < p)
- cmd->body.otf.langsys = msymbol__with_len (beg, p - beg);
- }
- else if (*p == '=')
- {
- for (beg = ++p; *p && *p != '+'; p++);
- if (beg < p)
- cmd->body.otf.gsub_features = msymbol__with_len (beg, p - beg);
- else
- cmd->body.otf.gsub_features = Mnil;
- }
- else if (*p == '+')
- {
- for (beg = ++p; *p && *p != '+'; p++);
- if (beg < p)
- cmd->body.otf.gpos_features = msymbol__with_len (beg, p - beg);
- else
- cmd->body.otf.gpos_features = Mnil;
- }
- else
- p++;
+ /* This is old format of "otf:...". Change it to ":otf=...". */
+ char *str = alloca (MSYMBOL_NAMELEN (sym) + 2);
+
+ sprintf (str, ":otf=");
+ strcat (str, name + 4);
+ sym = msymbol (str);
}
- return (cmd->body.otf.script == Mnil ? -1 : 0);
+ cmd->body.otf = mfont__get_capability (sym);
+ if (! cmd->body.otf)
+ return -1;
+ if (cmd->body.otf->script == Mnil)
+ {
+ cmd->body.otf = NULL;
+ return -1;
+ }
+ M17N_OBJECT_REF (cmd->body.otf);
+ cmd->type = FontLayoutCmdTypeOTF;
+ return 0;
}
if (MPLIST_SYMBOL_P (elt))
{
+ FontLayoutCmdCond *cond;
+
if (MPLIST_SYMBOL (elt) != Mcond)
MERROR (MERROR_DRAW, INVALID_CMD_ID);
elt = MPLIST_NEXT (elt);
cmd->type = FontLayoutCmdTypeCond;
- cmd->body.cond.n_cmds = len;
- MTABLE_CALLOC (cmd->body.cond.cmd_ids, len, MERROR_DRAW);
+ cond = &cmd->body.cond;
+ cond->seq_beg = cond->seq_end = -1;
+ cond->seq_from = cond->seq_to = 0;
+ cond->n_cmds = len;
+ MTABLE_CALLOC (cond->cmd_ids, len, MERROR_DRAW);
for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
{
int this_id = load_command (stage, elt, macros, INVALID_CMD_ID);
MERROR (MERROR_DRAW, INVALID_CMD_ID);
/* The above load_command may relocate stage->cmds. */
cmd = stage->cmds + CMD_ID_TO_INDEX (id);
- cmd->body.cond.cmd_ids[i] = this_id;
+ cond = &cmd->body.cond;
+ cond->cmd_ids[i] = this_id;
+ if (this_id <= CMD_ID_OFFSET_INDEX)
+ {
+ FontLayoutCmd *this_cmd
+ = stage->cmds + CMD_ID_TO_INDEX (this_id);
+
+ if (this_cmd->type == FontLayoutCmdTypeRule
+ && this_cmd->body.rule.src_type == SRC_SEQ)
+ {
+ int first_char = this_cmd->body.rule.src.seq.codes[0];
+
+ if (cond->seq_beg < 0)
+ {
+ /* The first SEQ command. */
+ cond->seq_beg = i;
+ cond->seq_from = cond->seq_to = first_char;
+ }
+ else if (cond->seq_end < 0)
+ {
+ /* The following SEQ command. */
+ if (cond->seq_from > first_char)
+ cond->seq_from = first_char;
+ else if (cond->seq_to < first_char)
+ cond->seq_to = first_char;
+ }
+ }
+ else
+ {
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
+ }
+ }
+ else
+ {
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
+ }
}
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
}
else
{
FontLayoutCmd cmd;
if (len > 4
- && ! strncmp (name, "otf:", 4)
- && load_otf_command (&cmd, name + 3) >= 0)
+ && ((name[0] == 'o' && name[1] == 't'
+ && name[2] == 'f' && name[3] == ':')
+ || (name[0] == ':' && name[1] == 'o' && name[2] == 't'
+ && name[3] == 'f' && name[4] == '='))
+ && load_otf_command (&cmd, sym) >= 0)
{
if (id == INVALID_CMD_ID)
{
}
else if (cmd->type == FontLayoutCmdTypeCond)
free (cmd->body.cond.cmd_ids);
+ else if (cmd->type == FontLayoutCmdTypeOTF)
+ M17N_OBJECT_UNREF (cmd->body.otf);
}
/* Load a generator from PLIST into a newly allocated FontLayoutStage,
MPlist *top = NULL, *plist;
MSymbol Mcategory = msymbol ("category");
MSymbol Mgenerator = msymbol ("generator");
+ MSymbol Mend = msymbol ("end");
MFontLayoutTable *layouter = NULL;
MCharTable *category = NULL;
MSymbol sym;
MPlist *elt;
+ if (MPLIST_SYMBOL_P (plist)
+ && MPLIST_SYMBOL (plist) == Mend)
+ break;
if (! MPLIST_PLIST (plist))
MERROR_GOTO (MERROR_FONT, finish);
elt = MPLIST_PLIST (plist);
int i;
int orig_from = from;
- if (ctx->cluster_begin_idx)
- {
- if (ctx->cluster_begin_pos > MGLYPH (from)->pos)
- ctx->cluster_begin_pos = MGLYPH (from)->pos;
- if (ctx->cluster_end_pos < MGLYPH (to)->pos)
- ctx->cluster_end_pos = MGLYPH (to)->pos;
- }
-
if (rule->src_type == SRC_SEQ)
{
int len;
if (i < len)
return 0;
to = from + len;
- MDEBUG_PRINT1 (" (SEQ 0x%X", rule->src.seq.codes[0]);
+ MDEBUG_PRINT3 ("\n [FLT] %*s(SEQ 0x%X", depth, "",
+ rule->src.seq.codes[0]);
}
else if (rule->src_type == SRC_RANGE)
{
return 0;
ctx->code_offset = head - rule->src.range.from;
to = from + 1;
- MDEBUG_PRINT2 (" (RANGE 0x%X-0x%X",
+ MDEBUG_PRINT4 ("\n [FLT] %*s(RANGE 0x%X-0x%X", depth, "",
rule->src.range.from, rule->src.range.to);
}
else if (rule->src_type == SRC_REGEX)
NMATCH, pmatch, 0);
if (result == 0 && pmatch[0].rm_so == 0)
{
- MDEBUG_PRINT3 (" (REGEX \"%s\" \"%s\" %d",
+ MDEBUG_PRINT5 ("\n [FLT] %*s(REGEX \"%s\" \"%s\" %d", depth, "",
rule->src.re.pattern,
ctx->encoded + from - ctx->encoded_offset,
pmatch[0].rm_eo);
if (from < 0)
return 0;
to = ctx->match_indices[rule->src.match_idx * 2 + 1];
- MDEBUG_PRINT1 (" (INDEX %d", rule->src.match_idx);
+ MDEBUG_PRINT3 ("\n [FLT] %*s(INDEX %d", depth, "", rule->src.match_idx);
}
consumed = 0;
MDEBUG_PRINT2 ("\n [FLT] %*s(COND", depth, "");
depth++;
for (i = 0; i < cond->n_cmds; i++)
- if ((pos = run_command (depth, cond->cmd_ids[i], gstring, from, to, ctx))
- != 0)
- break;
+ {
+ /* TODO: Write a code for optimization utilizaing the info
+ cond->seq_XXX. */
+ if ((pos = run_command (depth, cond->cmd_ids[i], gstring, from, to, ctx))
+ != 0)
+ break;
+ }
if (pos < 0)
MERROR (MERROR_DRAW, -1);
MDEBUG_PRINT (")");
static int
run_otf (int depth,
- FontLayoutCmdOTF *otf_cmd, MGlyphString *gstring, int from, int to,
+ MFontCapability *otf_cmd, MGlyphString *gstring, int from, int to,
FontLayoutContext *ctx)
{
#ifdef HAVE_OTF
- int gidx = gstring->used;
-
- to = mfont__ft_drive_otf (gstring, from, to,
- otf_cmd->script, otf_cmd->langsys,
- otf_cmd->gsub_features, otf_cmd->gpos_features);
- if (gidx < gstring->used)
- MGLYPH (gidx)->left_padding = ctx->left_padding;
+ int from_idx = gstring->used;
+
+ MDEBUG_PRINT4 ("\n [FLT] %*s(OTF %s,%s)", depth, "",
+ (! otf_cmd->features[MFONT_OTT_GSUB].str ? ""
+ : otf_cmd->features[MFONT_OTT_GSUB].str),
+ (! otf_cmd->features[MFONT_OTT_GPOS].str ? ""
+ : otf_cmd->features[MFONT_OTT_GPOS].str));
+ to = mfont__ft_drive_otf (gstring, from, to, otf_cmd);
+ if (ctx->cluster_begin_idx)
+ for (; from_idx < gstring->used; from_idx++)
+ UPDATE_CLUSTER_RANGE (ctx, gstring->glyphs[from_idx]);
#endif
return to;
}
+extern char *dump_combining_code (int code);
+
static int
run_command (int depth, int id, MGlyphString *gstring, int from, int to,
FontLayoutContext *ctx)
g = *(MGLYPH (from - 1));
g.type = GLYPH_CHAR;
g.code = ctx->code_offset + id;
- MDEBUG_PRINT1 (" (DIRECT 0x%X", g.code);
+ MDEBUG_PRINT3 ("\n [FLT] %*s(DIRECT 0x%X", depth, "", g.code);
if (ctx->combining_code)
g.combining_code = ctx->combining_code;
if (ctx->left_padding)
g.to = tmp->to;
}
APPEND_GLYPH (gstring, g);
+ UPDATE_CLUSTER_RANGE (ctx, g);
ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
MDEBUG_PRINT (")");
return (from);
else if (cmd->type == FontLayoutCmdTypeCond)
to = run_cond (depth, &cmd->body.cond, gstring, from, to, ctx);
else if (cmd->type == FontLayoutCmdTypeOTF)
- to = run_otf (depth, &cmd->body.otf, gstring, from, to, ctx);
+ to = run_otf (depth, cmd->body.otf, gstring, from, to, ctx);
if (to < 0)
return -1;
if (id <= CMD_ID_OFFSET_COMBINING)
{
ctx->combining_code = CMD_ID_TO_COMBINING_CODE (id);
+ MDEBUG_PRINT3 ("\n [FLT] %*s(CMB %s)", depth, "",
+ dump_combining_code (ctx->combining_code));
return from;
}
if (ctx->left_padding)
g.left_padding = ctx->left_padding;
APPEND_GLYPH (gstring, g);
+ UPDATE_CLUSTER_RANGE (ctx, g);
+ MDEBUG_PRINT3 ("\n [FLT] %*s(COPY 0x%X)", depth, "", g.code);
ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
return (from + 1);
}
case CMD_ID_CLUSTER_BEGIN:
if (! ctx->cluster_begin_idx)
{
- MDEBUG_PRINT1 (" <%d", MGLYPH (from)->pos);
+ MDEBUG_PRINT3 ("\n [FLT] %*s<%d", depth, "", MGLYPH (from)->pos);
ctx->cluster_begin_idx = gstring->used;
ctx->cluster_begin_pos = MGLYPH (from)->pos;
ctx->cluster_end_pos = MGLYPH (from)->to;
}
case CMD_ID_LEFT_PADDING:
+ MDEBUG_PRINT2 ("\n [FLT] %*s[", depth, "");
ctx->left_padding = 1;
return from;
case CMD_ID_RIGHT_PADDING:
if (gstring->used > 0)
- gstring->glyphs[gstring->used - 1].right_padding = 1;
+ {
+ MDEBUG_PRINT2 ("\n [FLT] %*s]", depth, "");
+ gstring->glyphs[gstring->used - 1].right_padding = 1;
+ }
return from;
}
Mcond = msymbol ("cond");
Mrange = msymbol ("range");
Mlayouter = msymbol ("layouter");
- McatCf = msymbol ("Cf");
flt_list = mplist ();
return 0;
}
}
int
-mfont__flt_run (MGlyphString *gstring, int from, int to,
- MSymbol layouter_name, MRealizedFace *ascii_rface)
+mfont__flt_run (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
{
int stage_idx = 0;
int gidx;
MCharTable *table;
int encoded_len;
int match_indices[NMATCH];
+ MSymbol layouter_name = rface->layouter;
MFontLayoutTable *layouter = get_font_layout_table (layouter_name);
+ MRealizedFace *ascii_rface = rface->ascii_rface;
FontLayoutStage *stage;
int from_pos, to_pos;
MGlyph dummy;
ctx.encoded[i] = (int) MGLYPH (gidx)->code;
MGLYPH (gidx)->code = (unsigned) MGLYPH (gidx)->c;
}
- for (; MGLYPH (to)->type != GLYPH_ANCHOR; to++, i++)
- {
- MGlyph *g = MGLYPH (to);
- unsigned code;
-
- if (g->category != McatCf
- && g->rface->rfont && g->rface->rfont->layouter != Mnil
- && g->rface->rfont->layouter != layouter_name)
- break;
- code = mfont__encode_char (g->rface->rfont, g->c);
- if (code == MCHAR_INVALID_CODE)
- break;
- g->code = g->c;
- ctx.encoded[i] = (int) code;
- }
-
ctx.encoded[i++] = '\0';
match_indices[0] = from;
int len = to - from;
int result;
- MDEBUG_PRINT1 ("\n [FLT] (STAGE %d", stage_idx);
+ ctx.code_offset = ctx.combining_code = ctx.left_padding = 0;
+ MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx, ctx.encoded);
+ if (mdebug__flag & mdebug_mask
+ && ctx.encoded_offset < to)
+ {
+ if (gstring->glyphs[ctx.encoded_offset].type == GLYPH_PAD)
+ fprintf (stderr, " (|");
+ else
+ fprintf (stderr, " (%X", gstring->glyphs[ctx.encoded_offset].code);
+ for (i = ctx.encoded_offset + 1; i < to; i++)
+ {
+ if (gstring->glyphs[i].type == GLYPH_PAD)
+ fprintf (stderr, " |");
+ else
+ fprintf (stderr, " %X", gstring->glyphs[i].code);
+ }
+ fprintf (stderr, ")");
+ }
+
gidx = gstring->used;
ctx.stage = stage;
- result = run_command (2, INDEX_TO_CMD_ID (0), gstring,
+ result = run_command (4, INDEX_TO_CMD_ID (0), gstring,
ctx.encoded_offset, to, &ctx);
MDEBUG_PRINT (")");
if (result < 0)
ctx.encoded[i - from] = ' ';
else if (! g->otf_encoded)
ctx.encoded[i - from] = (int) mchartable_lookup (table, g->code);
-#ifdef HAVE_FREETYPE
+#if defined (HAVE_FREETYPE) && defined (HAVE_OTF)
else
{
int c = mfont__ft_decode_otf (g);
}
ctx.encoded[i - from] = (c >= 0 ? c : 1);
}
-#endif /* HAVE_FREETYPE */
+#endif /* HAVE_FREETYPE && HAVE_OTF */
}
ctx.encoded[i - from] = '\0';
ctx.encoded_offset = from;
ctx.match_indices[1] = to;
}
- MDEBUG_PRINT (")\n");
-
if (from == to)
{
/* Somehow there's no glyph contributing to characters between
}
else
{
- /* Here we must check if all characters in the range is covered
- by some glyph(s). If not, change <pos> and <to> of glyphs to
- cover uncovered characters. */
+ /* Get actual glyph IDs of glyphs. Also check if all characters
+ in the range is covered by some glyph(s). If not, change
+ <pos> and <to> of glyphs to cover uncovered characters. */
int len = to_pos - from_pos;
int pos;
MGlyph **glyphs = alloca (sizeof (MGlyph) * len);
MGlyph *g, *gend = MGLYPH (to);
MGlyph *latest = gend;
+ for (g = MGLYPH (from); g != gend; g++)
+ if (g->type == GLYPH_CHAR && ! g->otf_encoded)
+ g->code = ((rface->rfont->driver->encode_char)
+ (NULL, (MFont *) rface->rfont, NULL, g->code));
for (i = 0; i < len; i++)
glyphs[i] = NULL;
for (g = MGLYPH (from); g != gend; g++)
latest = glyphs[i];
}
}
+ MDEBUG_PRINT ("\n [FLT] (RESULT (");
+ if (mdebug__flag & mdebug_mask
+ && ctx.encoded_offset < to)
+ {
+ if (gstring->glyphs[from].type == GLYPH_PAD)
+ fprintf (stderr, "|");
+ else
+ fprintf (stderr, "%X", gstring->glyphs[from].code);
+ for (from++; from < to; from++)
+ {
+ if (gstring->glyphs[from].type == GLYPH_PAD)
+ fprintf (stderr, " |");
+ else
+ fprintf (stderr, " %X", gstring->glyphs[from].code);
+ }
+ fprintf (stderr, "))");
+ }
+ MDEBUG_PRINT (")\n");
+
return to;
}