X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fface.c;h=983228c13a07ca71fe264902f677502e3d08bfdc;hb=d68a1ef5c7dc1dd24430bfb11dac9a9035c11428;hp=36ce285b2695b363b249e7aed5ea5683928f9baa;hpb=60452a0c3df0983f381ded76e95de254e57d86a6;p=m17n%2Fm17n-lib.git diff --git a/src/face.c b/src/face.c index 36ce285..983228c 100644 --- a/src/face.c +++ b/src/face.c @@ -17,7 +17,7 @@ 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. */ /***en @@ -243,7 +243,7 @@ serialize_face (void *val) MSymbol *key; MSymbol *type; MPlist *(*func) (MPlist *plist, void *val); - } serializer[MFACE_PROPERTY_MAX] + } serializer[MFACE_RATIO + 1] = { { &Mfoundry, &Msymbol }, { &Mfamily, &Msymbol }, { &Mweight, &Msymbol }, @@ -257,11 +257,9 @@ serialize_face (void *val) { &Mhline, NULL }, { &Mbox, NULL }, { &Mvideomode, &Msymbol }, - { NULL, NULL}, /* MFACE_HOOK_FUNC */ - { NULL, NULL}, /* MFACE_HOOK_ARG */ { &Mratio, &Minteger } }; - for (i = 0; i < MFACE_PROPERTY_MAX; i++) + for (i = 0; i <= MFACE_RATIO; i++) if (face->property[i] && serializer[i].key) { pl = mplist_add (pl, Msymbol, *serializer[i].key); @@ -363,7 +361,7 @@ deserialize_face (MPlist *plist) plist = MPLIST_NEXT (plist); if (MPLIST_TAIL_P (plist)) break; - if (index < 0 || index >= MFACE_PROPERTY_MAX) + if (index < 0 || index > MFACE_RATIO) continue; if (key == Mfoundry || key == Mfamily || key == Mweight || key == Mstyle || key == Mstretch || key == Madstyle @@ -419,8 +417,10 @@ mface__init () M17N_OBJECT_ADD_ARRAY (face_table, "Face"); Mface = msymbol_as_managing_key ("face"); - msymbol_put (Mface, Mtext_prop_serializer, (void *) serialize_face); - msymbol_put (Mface, Mtext_prop_deserializer, (void *) deserialize_face); + msymbol_put_func (Mface, Mtext_prop_serializer, + M17N_FUNC (serialize_face)); + msymbol_put_func (Mface, Mtext_prop_deserializer, + M17N_FUNC (deserialize_face)); Mforeground = msymbol ("foreground"); Mbackground = msymbol ("background"); @@ -442,7 +442,7 @@ mface__init () MSymbol *key; /* Index (enum face_property) of the face property. */ int index; - } mface_prop_data[MFACE_PROPERTY_MAX] = + } mface_prop_data[MFACE_HOOK_ARG + 1] = { { &Mfoundry, MFACE_FOUNDRY }, { &Mfamily, MFACE_FAMILY }, { &Mweight, MFACE_WEIGHT }, @@ -456,10 +456,8 @@ mface__init () { &Mhline, MFACE_HLINE }, { &Mbox, MFACE_BOX }, { &Mvideomode, MFACE_VIDEOMODE }, - { &Mhook_func, MFACE_HOOK_FUNC }, - { &Mhook_arg, MFACE_HOOK_ARG }, { &Mratio, MFACE_RATIO }, - }; + { &Mhook_arg, MFACE_HOOK_ARG } }; for (i = 0; i < MFACE_PROPERTY_MAX; i++) /* We add one to distinguish it from no-property. */ @@ -488,7 +486,7 @@ mface__init () mface__default->property[MFACE_HLINE] = hline; mface__default->property[MFACE_BOX] = box; mface__default->property[MFACE_VIDEOMODE] = Mnormal; - mface__default->property[MFACE_HOOK_FUNC] = (void *) noop_hook; + mface__default->hook = noop_hook; mface_normal_video = mface (); mface_normal_video->property[MFACE_VIDEOMODE] = (void *) Mnormal; @@ -604,14 +602,19 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font) MRealizedFace *rface; MRealizedFont *rfont; MFace merged_face = *(frame->face); - void **props; int i, j; MFaceHookFunc func; - MFont adjusted; + MFont spec; if (num == 0 && frame->rface && ! font) return frame->rface; + if (! mplist_find_by_value (frame->face->frame_list, frame)) + mplist_push (frame->face->frame_list, Mt, frame); + for (i = 0; i < num; i++) + if (! mplist_find_by_value (faces[i]->frame_list, frame)) + mplist_push (faces[i]->frame_list, Mt, frame); + for (i = 0; i < MFACE_PROPERTY_MAX; i++) for (j = num - 1; j >= 0; j--) if (faces[j]->property[i]) @@ -619,34 +622,27 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font) merged_face.property[i] = faces[j]->property[i]; break; } + if (font) { + if (font->type != MFONT_TYPE_REALIZED) + font = mfont_copy (font); for (i = 0; i <= MFACE_ADSTYLE; i++) if (font->property[i]) merged_face.property[i] = FONT_PROPERTY (font, i); if (font->size) { - if (font->size < 0) - { - double pt = - font->size; + int font_size; - adjusted = *font; - adjusted.size = pt * frame->dpi / 72.27 + 0.5; - font = &adjusted; - } - merged_face.property[MFACE_SIZE] = (void *) font->size; + if (font->size < 0) + font->size = ((double) (- font->size)) * frame->dpi / 72.27 + 0.5; + font_size = font->size; + merged_face.property[MFACE_SIZE] = (void *) font_size; + merged_face.property[MFACE_RATIO] = (void *) 0; } } - if (! mplist_find_by_value (frame->face->frame_list, frame)) - mplist_push (frame->face->frame_list, Mt, frame); - for (i = 0; i < num; i++) - if (! mplist_find_by_value (faces[i]->frame_list, frame)) - mplist_push (faces[i]->frame_list, Mt, frame); - - if ((int) merged_face.property[MFACE_SIZE] < 0 - || (merged_face.property[MFACE_RATIO] - && (int) merged_face.property[MFACE_RATIO] != 100)) + if (! font || ! font->size) { double font_size = (int) merged_face.property[MFACE_SIZE]; int ifont_size; @@ -658,70 +654,111 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font) { font_size *= (int) merged_face.property[MFACE_RATIO]; font_size /= 100; - merged_face.property[MFACE_RATIO] = 0; } ifont_size = font_size + 0.5; merged_face.property[MFACE_SIZE] = (void *) ifont_size; + merged_face.property[MFACE_RATIO] = (void *) 0; } merged_face.property[MFACE_FOUNDRY] = Mnil; rface = find_realized_face (frame, &merged_face, font); if (rface) - return rface; + { + if (font && font->type != MFONT_TYPE_REALIZED) + free (font); + return rface; + } MSTRUCT_CALLOC (rface, MERROR_FACE); mplist_push (frame->realized_face_list, Mt, rface); rface->frame = frame; rface->face = merged_face; + rface->font = font; + if (font) { - rface->font = mfont (); - *rface->font = *font; + if (font->type == MFONT_TYPE_SPEC) + rfont = (MRealizedFont *) mfont_find (frame, font, NULL, 0); + else if (font->type == MFONT_TYPE_OBJECT) + { + MFONT_INIT (&spec); + spec.size = (int) merged_face.property[MFONT_SIZE]; + if (font->property[MFONT_REGISTRY]) + spec.property[MFONT_REGISTRY] = font->property[MFONT_REGISTRY]; + else + mfont_put_prop (&spec, Mregistry, + (font->source == MFONT_SOURCE_X + ? Miso8859_1 : Municode_bmp)); + rfont = mfont__open (frame, font, &spec); + } + else + rfont = (MRealizedFont *) font; } - props = merged_face.property; - rface->rfontset = mfont__realize_fontset (frame, - (MFontset *) props[MFACE_FONTSET], - &merged_face, font); - num = 0; - rfont = NULL; - if (! font) + else { - MFont spec; + MFontset *fontset = (MFontset *) merged_face.property[MFACE_FONTSET]; + rface->rfontset = mfont__realize_fontset (frame, fontset, &merged_face, + font); + rfont = NULL; mfont__set_spec_from_face (&spec, &merged_face); - mfont_put_prop (&spec, Mregistry, Miso8859_1); - spec.source = MFONT_SOURCE_X; + mfont_put_prop (&spec, Mregistry, Municode_bmp); + spec.source = MFONT_SOURCE_FT; font = mfont__select (frame, &spec, 0); - if (! font) + if (font) + rfont = mfont__open (frame, font, &spec); + if (! rfont) { - mfont_put_prop (&spec, Mregistry, Municode_bmp); - spec.source = MFONT_SOURCE_FT; + mfont_put_prop (&spec, Mregistry, Miso8859_1); + spec.source = MFONT_SOURCE_X; font = mfont__select (frame, &spec, 0); + if (font) + rfont = mfont__open (frame, font, &spec); + } + if (! rfont) + { + num = 0; + rfont = mfont__lookup_fontset (rface->rfontset, NULL, &num, + Mlatin, Mnil, Mnil, size, 0); } - if (font) - rfont = mfont__open (frame, font, &spec); } - if (! rfont) - rfont = mfont__lookup_fontset (rface->rfontset, NULL, &num, - Mlatin, Mnil, Mnil, size, 0); + if (rfont) { rface->rfont = rfont; rface->layouter = rfont->layouter; + rfont->layouter = Mnil; work_gstring.glyphs[0].rface = rface; - work_gstring.glyphs[0].code = MCHAR_INVALID_CODE; + work_gstring.glyphs[0].g.code = MCHAR_INVALID_CODE; + work_gstring.glyphs[0].g.measured = 0; mfont__get_metric (&work_gstring, 0, 1); - rface->ascent = work_gstring.glyphs[0].ascent; - rface->descent = work_gstring.glyphs[0].descent; - work_gstring.glyphs[0].code + rface->ascent = work_gstring.glyphs[0].g.ascent; + rface->descent = work_gstring.glyphs[0].g.descent; + work_gstring.glyphs[0].g.code = mfont__encode_char (frame, (MFont *) rfont, NULL, ' '); - if (work_gstring.glyphs[0].code != MCHAR_INVALID_CODE) + if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE) { + work_gstring.glyphs[0].g.measured = 0; mfont__get_metric (&work_gstring, 0, 1); - rface->space_width = work_gstring.glyphs[0].width; + rface->space_width = work_gstring.glyphs[0].g.xadv; } else rface->space_width = rfont->spec.size / 10; + if (rfont->average_width) + rface->average_width = rfont->average_width >> 6; + else + { + work_gstring.glyphs[0].g.code + = mfont__encode_char (frame, (MFont *) rfont, NULL, 'x'); + if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE) + { + work_gstring.glyphs[0].g.measured = 0; + mfont__get_metric (&work_gstring, 0, 1); + rface->average_width = work_gstring.glyphs[0].g.xadv; + } + else + rface->average_width = rface->space_width; + } } else { @@ -729,16 +766,16 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font) rface->space_width = frame->space_width; } - rface->hline = (MFaceHLineProp *) props[MFACE_HLINE]; + rface->hline = (MFaceHLineProp *) merged_face.property[MFACE_HLINE]; if (rface->hline && rface->hline->width == 0) rface->hline = NULL; - rface->box = (MFaceBoxProp *) props[MFACE_BOX]; + rface->box = (MFaceBoxProp *) merged_face.property[MFACE_BOX]; if (rface->box && rface->box->width == 0) rface->box = NULL; rface->ascii_rface = rface; (*frame->driver->realize_face) (rface); - func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC]; + func = rface->face.hook; if (func && func != noop_hook) (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]); @@ -762,33 +799,99 @@ MGlyph * mface__for_chars (MSymbol script, MSymbol language, MSymbol charset, MGlyph *from_g, MGlyph *to_g, int size) { - MRealizedFont *rfont; + MRealizedFont *rfont = from_g->rface->rfont; MSymbol layouter; int num = to_g - from_g; int i; - rfont = from_g->rface->rfont; - if (script == Mlatin) + if (from_g->rface->font) + { + MRealizedFace *rface = from_g->rface, *new; + + if (! rfont) + rfont = mfontset__get_font (rface->frame, + rface->face.property[MFACE_FONTSET], + script, language, + rface->font, NULL); + else if (script != Mlatin) + rfont = mfontset__get_font (rface->frame, + rface->face.property[MFACE_FONTSET], + script, language, + (MFont *) rfont, NULL); + if (! rfont) + { + for (; from_g < to_g && from_g->rface->font; from_g++) + from_g->g.code = MCHAR_INVALID_CODE; + } + else + { + if (rface->rfont == rfont && rfont->layouter == Mnil) + new = rface; + else + { + MSTRUCT_MALLOC (new, MERROR_FACE); + mplist_push (rface->non_ascii_list, Mt, new); + *new = *rface; + new->rfont = rfont; + new->layouter = rfont->layouter; + rfont->layouter = Mnil; + new->non_ascii_list = NULL; + new->ascent = rfont->ascent >> 6; + new->descent = rfont->descent >> 6; + } + for (; from_g < to_g && from_g->rface->font; from_g++) + { + from_g->rface = new; + if (new->layouter) + { + MFLT *flt = mflt_get (new->layouter); + MCharTable *coverage; + + if (! flt + || ((coverage = mflt_coverage (flt)) + && ! (from_g->g.code + = (unsigned) mchartable_lookup (coverage, + from_g->g.c)))) + { + from_g->rface = rface; + from_g->g.code = mfont__encode_char (rfont->frame, + (MFont *) rfont, + NULL, from_g->g.c); + } + } + else + from_g->g.code = mfont__encode_char (rfont->frame, + (MFont *) rfont, + NULL, from_g->g.c); + } + } + return from_g; + } + + if (rfont && script == Mlatin) { for (i = 0; i < num; i++) { unsigned code = mfont__encode_char (rfont->frame, (MFont *) rfont, - NULL, from_g[i].c); + NULL, from_g[i].g.c); if (code == MCHAR_INVALID_CODE) break; - from_g[i].code = code; + from_g[i].g.code = code; } - if (i == num) - return to_g; + if (i == num || from_g[i].rface->font) + return from_g + i; } rfont = mfont__lookup_fontset (from_g->rface->rfontset, from_g, &num, script, language, charset, size, 0); if (rfont) - layouter = rfont->layouter; + { + layouter = rfont->layouter; + rfont->layouter = Mnil; + } else { - from_g->code = MCHAR_INVALID_CODE; + from_g->g.code = MCHAR_INVALID_CODE; num = 1; rfont = NULL; layouter = Mnil; @@ -824,8 +927,8 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset, new->non_ascii_list = NULL; if (rfont) { - new->ascent = rfont->ascent; - new->descent = rfont->descent; + new->ascent = rfont->ascent >> 6; + new->descent = rfont->descent >> 6; } } while (g < from_g) @@ -844,7 +947,7 @@ mface__free_realized (MRealizedFace *rface) MPLIST_DO (plist, rface->non_ascii_list) free (MPLIST_VAL (plist)); M17N_OBJECT_UNREF (rface->non_ascii_list); - if (rface->font) + if (rface->font && rface->font->type != MFONT_TYPE_REALIZED) free (rface->font); free (rface); } @@ -855,6 +958,7 @@ mface__update_frame_face (MFrame *frame) frame->rface = NULL; frame->rface = mface__realize (frame, NULL, 0, 0, NULL); frame->space_width = frame->rface->space_width; + frame->average_width = frame->rface->average_width; frame->ascent = frame->rface->ascent; frame->descent = frame->rface->descent; } @@ -1725,7 +1829,7 @@ mface_from_font (MFont *font) #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, - #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg + #Msize, #Mfontset, #Mratio, #Mhook_arg @return Ìá¤êÃͤη¿¤Ï $KEY ¤Ë°Í¸¤¹¤ë¡£¾åµ­¤Î¥­¡¼¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£ @@ -1734,7 +1838,7 @@ mface_from_font (MFont *font) /*** @seealso - mface_put_prop () + mface_put_prop (), mface_put_hook () @errors @c MERROR_FACE */ @@ -1745,13 +1849,37 @@ mface_get_prop (MFace *face, MSymbol key) int index = (int) msymbol_get (key, M_face_prop_index) - 1; if (index < 0) - MERROR (MERROR_FACE, NULL); + { + if (key == Mhook_func) + /* This unsafe code is for backward compatiblity. */ + return *(void **) &face->hook; + MERROR (MERROR_FACE, NULL); + } return face->property[index]; } /*=*/ /***en + @brief Get the hook function of a face. + + The mface_get_hook () function returns the hook function of face + $FACE. */ + +/***ja + @brief ¥Õ¥§¡¼¥¹¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÆÀ¤ë. + + ´Ø¿ô mface_get_hook () ¤Ï¥Õ¥§¡¼¥¹ $FACE ¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÊÖ¤¹¡£ */ + +MFaceHookFunc +mface_get_hook (MFace *face) +{ + return face->hook; +} + +/*=*/ + +/***en @brief Set a value of a face property. The mface_put_prop () function assigns $VAL to the property whose @@ -1806,22 +1934,32 @@ mface_put_prop (MFace *face, MSymbol key, void *val) int index = (int) msymbol_get (key, M_face_prop_index) - 1; MPlist *plist; - if (index < 0) - MERROR (MERROR_FACE, -1); - if (key == Mfontset) + if (key == Mhook_func) { - if (face->property[index]) - M17N_OBJECT_UNREF (face->property[index]); - M17N_OBJECT_REF (val); + /* This unsafe code is for backward compatiblity. */ + if (*(void **) &face->hook == val) + return 0; + *(void **) &face->hook = val; } - else if (key == Mhline) - val = get_hline_create (val); - else if (key == Mbox) - val = get_box_create (val); + else + { + if (index < 0) + MERROR (MERROR_FACE, -1); + if (key == Mfontset) + { + if (face->property[index]) + M17N_OBJECT_UNREF (face->property[index]); + M17N_OBJECT_REF (val); + } + else if (key == Mhline) + val = get_hline_create (val); + else if (key == Mbox) + val = get_box_create (val); - if (face->property[index] == val) - return 0; - face->property[index] = val; + if (face->property[index] == val) + return 0; + face->property[index] = val; + } MPLIST_DO (plist, face->frame_list) { @@ -1838,6 +1976,40 @@ mface_put_prop (MFace *face, MSymbol key, void *val) /*=*/ /***en + @brief Set a hook function to a face. + + The mface_set_hook () function sets the hook function of face + $FACE to $FUNC. */ + +/***ja + @brief ¥Õ¥§¡¼¥¹¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÀßÄꤹ¤ë. + + ´Ø¿ô mface_set_hook () ¤Ï¡¢¥Õ¥§¡¼¥¹ $FACE ¤Î¥Õ¥Ã¥¯´Ø¿ô¤ò$FUNC ¤ËÀß + Äꤹ¤ë¡£ */ + +int +mface_put_hook (MFace *face, MFaceHookFunc func) +{ + if (face->hook != func) + { + MPlist *plist; + face->hook = func; + + MPLIST_DO (plist, face->frame_list) + { + MFrame *frame = MPLIST_VAL (plist); + + frame->tick++; + if (face == frame->face) + mface__update_frame_face (frame); + } + } + return 0; +} + +/*=*/ + +/***en @brief Update a face. The mface_update () function update face $FACE on frame $FRAME by @@ -1852,7 +2024,7 @@ mface_put_prop (MFace *face, MSymbol key, void *val) void mface_update (MFrame *frame, MFace *face) { - MFaceHookFunc func = (MFaceHookFunc) face->property[MFACE_HOOK_FUNC]; + MFaceHookFunc func = face->hook; MPlist *rface_list; MRealizedFace *rface; @@ -1861,7 +2033,7 @@ mface_update (MFrame *frame, MFace *face) MPLIST_DO (rface_list, frame->realized_face_list) { rface = MPLIST_VAL (rface_list); - if ((MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC] == func) + if (rface->face.hook == func) (func) (&(rface->face), rface->face.property[MFACE_HOOK_ARG], rface->info); }