📄 fribidi.c
字号:
} else if (RL_TYPE(pp) == FRIBIDI_TYPE_L) { base_level = 0; base_dir = FRIBIDI_TYPE_L; break; } } /* If no strong base_dir was found, resort to the weak direction * that was passed on input. */ if (base_dir == FRIBIDI_TYPE_N) { if (*pbase_dir == FRIBIDI_TYPE_WR) { base_dir = FRIBIDI_TYPE_RTL; base_level = 1; } else if (*pbase_dir == FRIBIDI_TYPE_WL) { base_dir = FRIBIDI_TYPE_LTR; base_level = 0; } } } /* 1. Explicit Levels and Directions. TBD! */ compact_list(type_rl_list); /* 2. Explicit Overrides. TBD! */ compact_list(type_rl_list); /* 3. Terminating Embeddings and overrides. TBD! */ compact_list(type_rl_list); /* 4. Resolving weak types */ last_strong = base_dir; for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint prev_type = RL_TYPE(pp->prev); gint this_type = RL_TYPE(pp); gint next_type = RL_TYPE(pp->next); /* Remember the last strong character */ if (prev_type == FRIBIDI_TYPE_AL || prev_type == FRIBIDI_TYPE_R || prev_type == FRIBIDI_TYPE_L) last_strong = prev_type; /* W1. NSM */ if (this_type == FRIBIDI_TYPE_NSM) { if (prev_type == FRIBIDI_TYPE_SOT) RL_TYPE(pp) = FRIBIDI_TYPE_N; /* Will be resolved to base dir */ else RL_TYPE(pp) = prev_type; } /* W2: European numbers */ if (this_type == FRIBIDI_TYPE_N && last_strong == FRIBIDI_TYPE_AL) RL_TYPE(pp) = FRIBIDI_TYPE_AN; /* W3: Change ALs to R We have to do this for prev character as we would otherwise interfer with the next last_strong which is FRIBIDI_TYPE_AL. */ if (prev_type == FRIBIDI_TYPE_AL) RL_TYPE(pp->prev) = FRIBIDI_TYPE_R; /* W4. A single european separator changes to a european number. A single common separator between two numbers of the same type changes to that type. */ if (RL_LEN(pp) == 1) { TYPE_RULE_C(EN,ES,EN, EN); TYPE_RULE_C(EN,CS,EN, EN); TYPE_RULE_C(AN,CS,AN, AN); } /* W5. A sequence of European terminators adjacent to European numbers changes to All European numbers. */ if (this_type == FRIBIDI_TYPE_ET) { if (next_type == FRIBIDI_TYPE_EN || prev_type == FRIBIDI_TYPE_EN) { RL_TYPE(pp) = FRIBIDI_TYPE_EN; } } /* This type may have been overriden */ this_type = RL_TYPE(pp); /* W6. Otherwise change separators and terminators to other neutral */ if (this_type == FRIBIDI_TYPE_ET || this_type == FRIBIDI_TYPE_CS || this_type == FRIBIDI_TYPE_ES) RL_TYPE(pp) = FRIBIDI_TYPE_ON; /* W7. Change european numbers to L. */ if (prev_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_L) RL_TYPE(pp->prev) = FRIBIDI_TYPE_L; } /* Handle the two rules that effect pp->prev for the last element */ if (RL_TYPE (pp->prev) == FRIBIDI_TYPE_AL) /* W3 */ RL_TYPE(pp->prev) = FRIBIDI_TYPE_R; if (RL_TYPE (pp->prev) == FRIBIDI_TYPE_EN /* W7 */ && last_strong == FRIBIDI_TYPE_L) RL_TYPE(pp->prev) = FRIBIDI_TYPE_L; compact_list(type_rl_list); /* 5. Resolving Neutral Types */ DBG("Resolving neutral types.\n"); /* We can now collapse all separators and other neutral types to plain neutrals */ for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint this_type = RL_TYPE(pp); if ( this_type == FRIBIDI_TYPE_WS || this_type == FRIBIDI_TYPE_ON || this_type == FRIBIDI_TYPE_ES || this_type == FRIBIDI_TYPE_ET || this_type == FRIBIDI_TYPE_CS || this_type == FRIBIDI_TYPE_BN) RL_TYPE(pp) = FRIBIDI_TYPE_N; } compact_list(type_rl_list); for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint prev_type = RL_TYPE(pp->prev); gint this_type = RL_TYPE(pp); gint next_type = RL_TYPE(pp->next); if (this_type == FRIBIDI_TYPE_N) /* optimization! */ { /* "European and arabic numbers are treated as though they were R" */ if (prev_type == FRIBIDI_TYPE_EN || prev_type == FRIBIDI_TYPE_AN) prev_type = FRIBIDI_TYPE_R; if (next_type == FRIBIDI_TYPE_EN || next_type == FRIBIDI_TYPE_AN) next_type = FRIBIDI_TYPE_R; /* N1. */ TYPE_RULE_C(R,N,R, R); TYPE_RULE_C(L,N,L, L); /* N2. Any remaining neutrals takes the embedding direction */ if (RL_TYPE(pp) == FRIBIDI_TYPE_N) RL_TYPE(pp) = FRIBIDI_TYPE_E; } } compact_list(type_rl_list);#ifndef NO_STDIO if (fribidi_debug) print_types_re(type_rl_list);#endif /* 6. Resolving Implicit levels */ DBG("Resolving implicit levels.\n"); { gint level = base_level; max_level = base_level; for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint this_type = RL_TYPE(pp); /* This code should be expanded to handle explicit directions! */ /* Even */ if (level % 2 == 0) { if (this_type == FRIBIDI_TYPE_R) RL_LEVEL(pp) = level + 1; else if (this_type == FRIBIDI_TYPE_AN) RL_LEVEL(pp) = level + 2; else if (RL_TYPE(pp->prev) != FRIBIDI_TYPE_L && this_type == FRIBIDI_TYPE_EN) RL_LEVEL(pp) = level + 2; else RL_LEVEL(pp) = level; } /* Odd */ else { if ( this_type == FRIBIDI_TYPE_L || this_type == FRIBIDI_TYPE_AN || this_type == FRIBIDI_TYPE_EN) RL_LEVEL(pp) = level+1; else RL_LEVEL(pp) = level; } if (RL_LEVEL(pp) > max_level) max_level = RL_LEVEL(pp); } } compact_list(type_rl_list);#ifndef NO_STDIO if (fribidi_debug) { print_bidi_string(str); print_resolved_levels(type_rl_list); print_resolved_types(type_rl_list); }#endif *ptype_rl_list = type_rl_list; *pmax_level = max_level; *pbase_dir = base_dir;}/*======================================================================// Here starts the exposed front end functions.//----------------------------------------------------------------------*//*======================================================================// fribidi_log2vis() calls the function_analyse_string() and then// does reordering and fills in the output strings.//----------------------------------------------------------------------*/void fribidi_log2vis(/* input */ FriBidiChar *str, gint len, FriBidiCharType *pbase_dir, /* output */ FriBidiChar *visual_str, guint16 *position_L_to_V_list, guint16 *position_V_to_L_list, guint8 *embedding_level_list ){ TypeLink *type_rl_list, *pp = NULL; gint max_level; gboolean private_V_to_L = FALSE; if (len == 0) return; /* If l2v is to be calculated we must have l2v as well. If it is not given by the caller, we have to make a private instance of it. */ if (position_L_to_V_list && !position_V_to_L_list) { private_V_to_L = TRUE; position_V_to_L_list = g_new(guint16, len+1); } if (len > FRIBIDI_MAX_STRING_LENGTH) {#ifndef NO_STDIO fprintf(stderr, "Fribidi can't handle strings > 65000 chars!\n");#endif return; } fribidi_analyse_string(str, len, pbase_dir, /* output */ &type_rl_list, &max_level); /* 7. Reordering resolved levels */ DBG("Reordering.\n"); { gint level_idx; gint i; /* Set up the ordering array to sorted order and copy the logical string to the visual */ if (position_L_to_V_list) for (i=0; i<len+1; i++) position_L_to_V_list[i]=i; if (visual_str) for (i=0; i<len+1; i++) visual_str[i] = str[i]; /* Assign the embedding level array */ if (embedding_level_list) for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint i; gint pos = RL_POS(pp); gint len = RL_LEN(pp); gint level = RL_LEVEL(pp); for (i=0; i<len; i++) embedding_level_list[pos + i] = level; } /* Reorder both the outstring and the order array*/ if (visual_str || position_V_to_L_list) { if (visual_str) /* Mirror all characters that are in odd levels and have mirrors */ for (pp = type_rl_list->next; pp->next; pp = pp->next) { if (RL_LEVEL(pp) % 2 == 1) { gint i; for (i=RL_POS(pp); i<RL_POS(pp)+RL_LEN(pp); i++) { FriBidiChar mirrored_ch; if (fribidi_get_mirror_char(visual_str[i], &mirrored_ch)) visual_str[i] = mirrored_ch; } } } /* Reorder */ for (level_idx = max_level; level_idx>0; level_idx--) { for (pp = type_rl_list->next; pp->next; pp = pp->next) { if (RL_LEVEL(pp) >= level_idx) { /* Find all stretches that are >= level_idx */ gint len = RL_LEN(pp); gint pos = RL_POS(pp); TypeLink *pp1 = pp->next; while(pp1->next && RL_LEVEL(pp1) >= level_idx) { len+= RL_LEN(pp1); pp1 = pp1->next; } pp = pp1->prev; if (visual_str) bidi_string_reverse(visual_str+pos, len); if (position_V_to_L_list) int16_array_reverse(position_V_to_L_list+pos, len); } } } } /* Convert the l2v list to v2l */ if (position_V_to_L_list && position_L_to_V_list) for (i=0; i<len; i++) position_V_to_L_list[position_L_to_V_list[i]] = i; } /* Free up the rl_list */ /* At this point, pp points to the last link or (rarely) might be NULL */ if (!pp) for (pp = type_rl_list->next; pp->next; pp = pp->next) /* Nothing */; pp->next = free_type_links; free_type_links = type_rl_list; /* Free up V_to_L if we allocated it */ if (private_V_to_L) g_free(position_V_to_L_list); }/*======================================================================// fribidi_embedding_levels() is used in order to just get the// embedding levels.//----------------------------------------------------------------------*/void fribidi_log2vis_get_embedding_levels( /* input */ FriBidiChar *str, gint len, FriBidiCharType *pbase_dir, /* output */ guint8 *embedding_level_list ){ TypeLink *type_rl_list, *pp; gint max_level; if (len = 0) return; fribidi_analyse_string(str, len, pbase_dir, /* output */ &type_rl_list, &max_level); for (pp = type_rl_list->next; pp->next; pp = pp->next) { gint i; gint pos = RL_POS(pp); gint len = RL_LEN(pp); gint level = RL_LEVEL(pp); for (i=0; i<len; i++) embedding_level_list[pos + i] = level; } /* Free up the rl_list */ pp->next = free_type_links; free_type_links = type_rl_list;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -