patch: remapGlyph / smart quote options, etc


Subject: patch: remapGlyph / smart quote options, etc
From: WJCarpenter (bill-abisource@carpenter.ORG)
Date: Sun Jul 09 2000 - 13:27:11 CDT


The attached patch, taken against 070900 nightly sources, implements
the use of the user preference items in the RemapGlyph* series, which
by default just makes the visible replacements for zero-width smart
quote glyphs (ie, the same behavior as was hard-wired a few days
ago). The changes are all XP or Unix and have been tested on Linux.

Besides the changes to respect the preference items, per se, I
changed a couple of GDK *_wc() calls in the Unix stuff to get answers
that are more useful to us. This is not the One True Fix for Abi's
use of GDK, but it's needed for smart quote remapping to work. [[For
anyone who cares, gdk_text_width_wc(somefont, &someChar, 1) typically
returns a non-zero width for an zero-width character, whereas
gdk_char_width_wc(somefont, someChar) returns zero as expected.]] The
One True Fix has to come later, and will take some more education for
me or some Doing It by someone else.

I actually had those GDK call changes in my code for a while, but I
didn't submit them because I forgot that they mattered. But without
them, anyone else checking out the recent smart quote fixes probably
has been seeing a radically different picture from what I have been
seeing.

Here is a snip from the comments I left in the code about how this
works (this is in case any of you are actually managers and want to
feel like you've "read through some code" without actually doing that
:-):

// Here is how the remapGlyph works.

// * If preference value RemapGlyphsMasterSwitch is not true, no
// remapping is done.

// * RemapGlyphsTable is a list of pairs of characters, with the
// first of each pair being the actual character and the second of
// each pair being the replacement. Normally, a character will
// not be remapped unless it is zero-width. If it is listed as an
// actual character in RemapGlyphsTable, then the affiliated
// replacement character is returned. If it is not listed in
// RemapGlyphsTable, then the value of RemapGlyphsDefault is used,
// though if the default value is null, it is not used (it is
// tricky to specify null due to XML parsing).

// * Remapping is not recursive/iterative/whatever. So, if you
// remap from a zero-width character to another zero-width
// character, that's what you get.

// * If this function is called with noMatterWhat true, or if the
// preference value RemapGlyphsNoMatterWhat is true, the above algorithm
// is changed a bit. Characters listed as actual characters in the table
// are given replacement values even if they are not zero-width, however
// the default replacement character is used only if the actual character
// really has zero-width. (The intent of the function parameter is that
// the calling function may have already determined that the character is
// zero-width, and it may be arbitrarily expensive to check, so a
// redundant check can be avoided.) (The intent of the user preference
// value is to just give a way to force the algorithm's hand "just in
// case".)

// * Because we are constantly checking those user preference values
// (sometimes it might be 2-3 times per character rendered), we cache
// their values as static members of the GR_Graphics class. The table of
// actual and replacement characters is split into two arrays of "src"
// and "dst" characters, respectively. If the table had an odd number of
// characters, the extra dangling character is ignored.

// * Linear searching is done looking for the actual character, so the
// implementation is assuming that the RemapGlyphsTable is not too big.
// Also, because null-terminated UTF8 and Unicode strings are all over
// the place, you can remap a null character nor remap to a null
// character. In office productivity apps, this probably won't be a
// problem.

-- 
bill@carpenter.ORG (WJCarpenter)    PGP 0x91865119
38 95 1B 69 C9 C6 3D 25    73 46 32 04 69 D6 ED F3

diff -ru abi-070900/src/af/gr/unix/gr_UnixGraphics.cpp abi-nightly/src/af/gr/unix/gr_UnixGraphics.cpp --- abi-070900/src/af/gr/unix/gr_UnixGraphics.cpp Fri Jul 7 16:46:45 2000 +++ abi-nightly/src/af/gr/unix/gr_UnixGraphics.cpp Sun Jul 9 00:00:16 2000 @@ -202,7 +202,7 @@ GdkWChar cChar = c; GdkFont* pFont = m_pFont->getGdkFont(); - width = gdk_text_width_wc (pFont, &cChar, 1); + width = gdk_char_width_wc (pFont, cChar); return width; } #if 0 @@ -232,11 +232,11 @@ { cChar = s[i + iOffset]; - width = gdk_text_width_wc (pFont, &cChar, 1); + width = gdk_char_width_wc (pFont, cChar); if (width == 0) { cChar = remapGlyph(s[i + iOffset], UT_TRUE); - width = gdk_text_width_wc (pFont, &cChar, 1); + width = gdk_char_width_wc (pFont, cChar); } charWidth += width; diff -ru abi-070900/src/af/gr/xp/gr_Graphics.cpp abi-nightly/src/af/gr/xp/gr_Graphics.cpp --- abi-070900/src/af/gr/xp/gr_Graphics.cpp Fri Jul 7 16:46:46 2000 +++ abi-nightly/src/af/gr/xp/gr_Graphics.cpp Sun Jul 9 10:27:43 2000 @@ -27,8 +27,20 @@ #include "ut_assert.h" #include "ut_string.h" #include "ut_units.h" +#include "ut_growbuf.h" #include "ut_debugmsg.h" +// static class member initializations +UT_Bool GR_Graphics::m_bRemapGlyphsMasterSwitch = UT_TRUE; +UT_Bool GR_Graphics::m_bRemapGlyphsNoMatterWhat = UT_FALSE; +UT_UCSChar GR_Graphics::m_ucRemapGlyphsDefault = 0xB0; +UT_UCSChar *GR_Graphics::m_pRemapGlyphsTableSrc = 0; +UT_UCSChar *GR_Graphics::m_pRemapGlyphsTableDst = 0; +UT_uint32 GR_Graphics::m_iRemapGlyphsTableLen = 0; + +XAP_PrefsScheme *GR_Graphics::m_pPrefsScheme = 0; +UT_uint32 GR_Graphics::m_uTick = 0; + GR_Font::GR_Font() { } @@ -105,35 +117,127 @@ UT_UCSChar GR_Graphics::remapGlyph(const UT_UCSChar actual, UT_Bool noMatterWhat) { - // This routine is for remapping zero-width characters, which - // represent undefined glyphs in the font, into something useful - // and visible. This is most useful for the smart quote - // characters, which are specially treated. Other zero-width - // characters are mapped to a generic filler character. + + // Here is how the remapGlyph works. + + // * If preference value RemapGlyphsMasterSwitch is not true, no + // remapping is done. + + // * RemapGlyphsTable is a list of pairs of characters, with the + // first of each pair being the actual character and the second of + // each pair being the replacement. Normally, a character will + // not be remapped unless it is zero-width. If it is listed as an + // actual character in RemapGlyphsTable, then the affiliated + // replacement character is returned. If it is not listed in + // RemapGlyphsTable, then the value of RemapGlyphsDefault is used, + // though if the default value is null, it is not used (it is + // tricky to specify null due to XML parsing). + + // * Remapping is not recursive/iterative/whatever. So, if you + // remap from a zero-width character to another zero-width + // character, that's what you get. + + // * If this function is called with noMatterWhat true, or if the + // preference value RemapGlyphsNoMatterWhat is true, the above algorithm + // is changed a bit. Characters listed as actual characters in the table + // are given replacement values even if they are not zero-width, however + // the default replacement character is used only if the actual character + // really has zero-width. (The intent of the function parameter is that + // the calling function may have already determined that the character is + // zero-width, and it may be arbitrarily expensive to check, so a + // redundant check can be avoided.) (The intent of the user preference + // value is to just give a way to force the algorithm's hand "just in + // case".) + + // * Because we are constantly checking those user preference values + // (sometimes it might be 2-3 times per character rendered), we cache + // their values as static members of the GR_Graphics class. The table of + // actual and replacement characters is split into two arrays of "src" + // and "dst" characters, respectively. If the table had an odd number of + // characters, the extra dangling character is ignored. + + // * Linear searching is done looking for the actual character, so the + // implementation is assuming that the RemapGlyphsTable is not too big. + // Also, because null-terminated UTF8 and Unicode strings are all over + // the place, you can remap a null character nor remap to a null + // character. In office productivity apps, this probably won't be a + // problem. + + UT_UCSChar remap = actual; if (!m_pApp) { - UT_DEBUGMSG(("m_pApp in GR_Graphics object is null, glyphs not remapped\n")); + UT_DEBUGMSG(("GR_Graphics::remapGlyph() has no XAP_App*, glyphs not remapped\n")); return actual; } - UT_UCSChar remap = actual; - unsigned short w = 1; - - w = measureUnRemappedChar(actual); - if (noMatterWhat || w == 0) + XAP_Prefs *p = m_pApp->getPrefs(); + UT_ASSERT(m_pApp->getPrefs()); + XAP_PrefsScheme *s = p->getCurrentScheme(UT_FALSE); + UT_ASSERT(p->getCurrentScheme(UT_FALSE)); + UT_uint32 t = s->getTickCount(); + if (m_pPrefsScheme != s || m_uTick != t) { - switch (actual) + // refresh cached preference values + UT_DEBUGMSG(("GR_Graphics::remapGlyph() refreshing cached values\n")); + m_pPrefsScheme = s; + m_uTick = t; + p->getPrefsValueBool((const char *)"RemapGlyphsMasterSwitch", &m_bRemapGlyphsMasterSwitch); + p->getPrefsValueBool((const char *)"RemapGlyphsNoMatterWhat", &m_bRemapGlyphsNoMatterWhat); + + const XML_Char *table_utf8, *default_utf8; + UT_GrowBuf gb; + const UT_UCSChar *tbl; + + p->getPrefsValue((const char *)"RemapGlyphsDefault", &default_utf8); + UT_ASSERT(p->getPrefsValue((const char *)"RemapGlyphsDefault", &default_utf8)); + UT_decodeUTF8string(default_utf8, UT_XML_strlen(default_utf8), &gb); + m_ucRemapGlyphsDefault = *(gb.getPointer(0)); // might be null + + p->getPrefsValue((const char *)"RemapGlyphsTable", &table_utf8); + UT_ASSERT(p->getPrefsValue((const char *)"RemapGlyphsTable", &table_utf8)); + gb.truncate(0); + UT_decodeUTF8string(table_utf8, UT_XML_strlen(table_utf8), &gb); + + UT_uint32 doublelength; + doublelength = gb.getLength(); + m_iRemapGlyphsTableLen = doublelength / 2; + delete m_pRemapGlyphsTableSrc; + delete m_pRemapGlyphsTableDst; + m_pRemapGlyphsTableSrc = 0; + m_pRemapGlyphsTableDst = 0; + if (m_iRemapGlyphsTableLen) { - case UCS_LQUOTE: remap = '`'; break; - case UCS_RQUOTE: remap = '\''; break; - case UCS_RDBLQUOTE: remap = '"'; break; - case UCS_LDBLQUOTE: remap = '"'; break; - default: remap = (w ? actual : 0xB0); break; + m_pRemapGlyphsTableSrc = new UT_UCSChar[m_iRemapGlyphsTableLen]; + m_pRemapGlyphsTableDst = new UT_UCSChar[m_iRemapGlyphsTableLen]; + tbl = gb.getPointer(0); + for (UT_uint32 tdex=0; tdex<m_iRemapGlyphsTableLen; ++tdex) + { + m_pRemapGlyphsTableSrc[tdex] = tbl[2 * tdex]; + m_pRemapGlyphsTableDst[tdex] = tbl[2 * tdex + 1]; + UT_DEBUGMSG(("RemapGlyphsTable[%d] 0x%04x -> 0x%04x\n", tdex, m_pRemapGlyphsTableSrc[tdex], m_pRemapGlyphsTableDst[tdex])); + } } } - XAP_Prefs *p = m_pApp->getPrefs(); - XAP_PrefsScheme *s = p->getCurrentScheme(UT_FALSE); - UT_uint32 t = s->getTickCount(); - if (remap != actual) UT_DEBUGMSG(("remapGlyph 0x%04X -> 0x%04X %d %d tick: %d [%d]\n", actual, remap, noMatterWhat, w, t, s)); + if (!m_bRemapGlyphsMasterSwitch) return (actual); + UT_uint32 width = 0xFFFF; + if (noMatterWhat || m_bRemapGlyphsNoMatterWhat || !(width = measureUnRemappedChar(actual))) + { + UT_Bool try_default = UT_TRUE; + for (UT_uint32 tdex=0; tdex<m_iRemapGlyphsTableLen; ++tdex) + { + if (actual == m_pRemapGlyphsTableSrc[tdex]) + { + remap = m_pRemapGlyphsTableDst[tdex]; + try_default = UT_FALSE; + break; + } + } + if (try_default && m_ucRemapGlyphsDefault) + { + if (width == 0xFFFF) width = measureUnRemappedChar(actual); + if (!width) remap = m_ucRemapGlyphsDefault; + } + } + if (remap != actual) UT_DEBUGMSG(("GR_Graphics::remapGlyph( 0x%04X ) -> 0x%04X tick: %d [%d]\n", actual, remap, t, s)); return remap; } diff -ru abi-070900/src/af/gr/xp/gr_Graphics.h abi-nightly/src/af/gr/xp/gr_Graphics.h --- abi-070900/src/af/gr/xp/gr_Graphics.h Fri Jul 7 16:46:46 2000 +++ abi-nightly/src/af/gr/xp/gr_Graphics.h Sat Jul 8 00:26:22 2000 @@ -27,6 +27,7 @@ class UT_RGBColor; class XAP_App; +class XAP_PrefsScheme; /* GR_Font is a reference to a font. As it happens, everything about fonts @@ -57,6 +58,7 @@ an attempt at a general purpose portability layer. Rather, it contains only functions which are needed. */ + class GR_Graphics { public: @@ -198,6 +200,15 @@ UT_uint32 m_iZoomPercentage; UT_Bool m_bLayoutResolutionModeEnabled; + static UT_Bool m_bRemapGlyphsMasterSwitch; + static UT_Bool m_bRemapGlyphsNoMatterWhat; + static UT_UCSChar m_ucRemapGlyphsDefault; + static UT_UCSChar *m_pRemapGlyphsTableSrc; + static UT_UCSChar *m_pRemapGlyphsTableDst; + static UT_uint32 m_iRemapGlyphsTableLen; + + static XAP_PrefsScheme *m_pPrefsScheme; + static UT_uint32 m_uTick; }; #endif /* GR_GRAPHICS_H */ diff -ru abi-070900/src/af/xap/xp/xap_Frame.cpp abi-nightly/src/af/xap/xp/xap_Frame.cpp --- abi-070900/src/af/xap/xp/xap_Frame.cpp Fri Jul 7 16:46:50 2000 +++ abi-nightly/src/af/xap/xp/xap_Frame.cpp Sat Jul 8 00:54:20 2000 @@ -190,32 +190,6 @@ szMenuLayoutName = szMenuLayoutDefaultValue; UT_cloneString((char *&)m_szMenuLayoutName,szMenuLayoutName); - - { - UT_GrowBuf gb; - UT_UCSChar *buf; - const XML_Char *table = 0; - UT_DEBUGMSG(("==============================\n")); - pApp->getPrefsValue((const char *)"RemapGlyphsTable", &table); - UT_decodeUTF8string(table, UT_XML_strlen(table), &gb); - buf = gb.getPointer(0); - for (int i=0; i<gb.getLength(); ++i) - { - UT_DEBUGMSG((" table %2d: 0x%04X %c\n", i, *(buf + i), *(buf + i) < 256 ? *(buf + i) : '-')); - } - //UT_DEBUGMSG(("table |%s|, sizeof XML_Char %d\n", table, sizeof(XML_Char))); - gb.truncate(0); - pApp->getPrefsValue((const char *)"RemapGlyphsDefault", &table); - UT_decodeUTF8string(table, UT_XML_strlen(table), &gb); - buf = gb.getPointer(0); - UT_DEBUGMSG(("default %2d: 0x%04X %c\n", 99, *(buf), *(buf) < 256 ? *(buf) : '-')); - for (int tdex=0; tdex<strlen(table); ++tdex) - { - UT_DEBUGMSG(("utf8 default table[%d]: %x\n", tdex, table[tdex])); - } - UT_DEBUGMSG(("==============================\n")); - } - ////////////////////////////////////////////////////////////////// // select language for menu labels //////////////////////////////////////////////////////////////////



This archive was generated by hypermail 2b25 : Sun Jul 09 2000 - 13:29:21 CDT