Huw Davies : riched20: Maintain a list of styles and reuse them if possible.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Nov 10 10:36:20 CST 2015


Module: wine
Branch: master
Commit: b241276f50ba38f0e76b3c3645d059b22d30f652
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b241276f50ba38f0e76b3c3645d059b22d30f652

Author: Huw Davies <huw at codeweavers.com>
Date:   Mon Nov  9 16:11:43 2015 +0000

riched20: Maintain a list of styles and reuse them if possible.

Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/riched20/editor.c  |  8 ++++-
 dlls/riched20/editor.h  |  3 +-
 dlls/riched20/editstr.h |  2 ++
 dlls/riched20/run.c     |  4 +--
 dlls/riched20/style.c   | 79 ++++++++++++++++++++++++++++++-------------------
 5 files changed, 62 insertions(+), 34 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index ec584eb..bbb0cc0 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -533,7 +533,7 @@ void ME_RTFCharAttrHook(RTF_Info *info)
     ME_Style *style2;
     RTFFlushOutputBuffer(info);
     /* FIXME too slow ? how come ? */
-    style2 = ME_ApplyStyle(info->style, &fmt);
+    style2 = ME_ApplyStyle(info->editor, info->style, &fmt);
     ME_ReleaseStyle(info->style);
     info->style = style2;
     info->styleChanged = TRUE;
@@ -2920,6 +2920,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10, DWORD
 
   ed->wheel_remain = 0;
 
+  list_init( &ed->style_list );
   OleInitialize(NULL);
 
   return ed;
@@ -2929,6 +2930,7 @@ void ME_DestroyEditor(ME_TextEditor *editor)
 {
   ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
   ME_DisplayItem *p = pFirst, *pNext = NULL;
+  ME_Style *s, *cursor2;
   int i;
 
   ME_ClearTempStyle(editor);
@@ -2938,6 +2940,10 @@ void ME_DestroyEditor(ME_TextEditor *editor)
     ME_DestroyDisplayItem(p);
     p = pNext;
   }
+
+  LIST_FOR_EACH_ENTRY_SAFE( s, cursor2, &editor->style_list, ME_Style, entry )
+      ME_DestroyStyle( s );
+
   ME_ReleaseStyle(editor->pBuffer->pDefaultStyle);
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index f22f0e6..a63dea6 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -69,9 +69,10 @@ static inline const char *debugstr_run( const ME_Run *run )
 /* style.c */
 ME_Style *ME_MakeStyle(CHARFORMAT2W *style) DECLSPEC_HIDDEN;
 void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN;
+void ME_DestroyStyle(ME_Style *item) DECLSPEC_HIDDEN;
 void ME_ReleaseStyle(ME_Style *item) DECLSPEC_HIDDEN;
 ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) DECLSPEC_HIDDEN;
-ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style) DECLSPEC_HIDDEN;
+ME_Style *ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style) DECLSPEC_HIDDEN;
 HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN;
 void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont) DECLSPEC_HIDDEN;
 void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 3e98dac..be925db 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -78,6 +78,7 @@ typedef struct tagME_Style
   TEXTMETRICW tm; /* cached font metrics for the style */
   int nRefs; /* reference count */
   SCRIPT_CACHE script_cache;
+  struct list entry;
 } ME_Style;
 
 typedef enum {
@@ -444,6 +445,7 @@ typedef struct tagME_TextEditor
 
   BOOL bMouseCaptured;
   int wheel_remain;
+  struct list style_list;
 } ME_TextEditor;
 
 typedef struct tagME_Context
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index d261213..7016932 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -695,7 +695,7 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
     ME_Style *s;
     if (!editor->pBuffer->pCharStyle)
       editor->pBuffer->pCharStyle = ME_GetInsertStyle(editor, 0);
-    s = ME_ApplyStyle(editor->pBuffer->pCharStyle, pFmt);
+    s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt);
     ME_ReleaseStyle(editor->pBuffer->pCharStyle);
     editor->pBuffer->pCharStyle = s;
   } else {
@@ -753,7 +753,7 @@ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, C
 
   for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun ))
   {
-    ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt);
+    ME_Style *new_style = ME_ApplyStyle(editor, run->member.run.style, pFmt);
 
     add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs,
                            run->member.run.len, &run->member.run.style->fmt );
diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c
index 37f56d9..06c0e6f 100644
--- a/dlls/riched20/style.c
+++ b/dlls/riched20/style.c
@@ -150,21 +150,22 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style)
   memset(&s->tm, 0, sizeof(s->tm));
   s->tm.tmAscent = -1;
   s->script_cache = NULL;
+  list_init(&s->entry);
   all_refs++;
   TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs);
   return s;
 }
 
 #define COPY_STYLE_ITEM(mask, member) \
-  if (style->dwMask & mask) { \
-    s->fmt.dwMask |= mask;\
-    s->fmt.member = style->member;\
+  if (mod->dwMask & mask) { \
+    fmt.dwMask |= mask;\
+    fmt.member = mod->member;\
   }
 
 #define COPY_STYLE_ITEM_MEMCPY(mask, member) \
-  if (style->dwMask & mask) { \
-    s->fmt.dwMask |= mask;\
-    CopyMemory(s->fmt.member, style->member, sizeof(style->member));\
+  if (mod->dwMask & mask) { \
+    fmt.dwMask |= mask;\
+    CopyMemory(fmt.member, mod->member, sizeof(mod->member));\
   }
 
 void ME_InitCharFormat2W(CHARFORMAT2W *pFmt)
@@ -173,10 +174,12 @@ void ME_InitCharFormat2W(CHARFORMAT2W *pFmt)
   pFmt->cbSize = sizeof(CHARFORMAT2W);
 }
 
-ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style)
+ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod)
 {
-  ME_Style *s = ME_MakeStyle(&sSrc->fmt);
-  assert(style->cbSize == sizeof(CHARFORMAT2W));
+  CHARFORMAT2W fmt = sSrc->fmt;
+  ME_Style *s;
+
+  assert(mod->cbSize == sizeof(CHARFORMAT2W));
   COPY_STYLE_ITEM(CFM_ANIMATION, bAnimation);
   COPY_STYLE_ITEM(CFM_BACKCOLOR, crBackColor);
   COPY_STYLE_ITEM(CFM_CHARSET, bCharSet);
@@ -186,9 +189,9 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style)
   COPY_STYLE_ITEM(CFM_LCID, lcid);
   COPY_STYLE_ITEM(CFM_OFFSET, yOffset);
   COPY_STYLE_ITEM(CFM_REVAUTHOR, bRevAuthor);
-  if (style->dwMask & CFM_SIZE) {
-    s->fmt.dwMask |= CFM_SIZE;
-    s->fmt.yHeight = min(style->yHeight, yHeightCharPtsMost * 20);
+  if (mod->dwMask & CFM_SIZE) {
+    fmt.dwMask |= CFM_SIZE;
+    fmt.yHeight = min(mod->yHeight, yHeightCharPtsMost * 20);
   }
   COPY_STYLE_ITEM(CFM_SPACING, sSpacing);
   COPY_STYLE_ITEM(CFM_STYLE, sStyle);
@@ -197,31 +200,46 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style)
   /* FIXME: this is not documented this way, but that's the more logical */
   COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily);
 
-  s->fmt.dwEffects &= ~(style->dwMask);
-  s->fmt.dwEffects |= style->dwEffects & style->dwMask;
-  s->fmt.dwMask |= style->dwMask;
-  if (style->dwMask & CFM_COLOR)
+  fmt.dwEffects &= ~(mod->dwMask);
+  fmt.dwEffects |= mod->dwEffects & mod->dwMask;
+  fmt.dwMask |= mod->dwMask;
+  if (mod->dwMask & CFM_COLOR)
   {
-    if (style->dwEffects & CFE_AUTOCOLOR)
-      s->fmt.dwEffects |= CFE_AUTOCOLOR;
+    if (mod->dwEffects & CFE_AUTOCOLOR)
+      fmt.dwEffects |= CFE_AUTOCOLOR;
     else
-      s->fmt.dwEffects &= ~CFE_AUTOCOLOR;
+      fmt.dwEffects &= ~CFE_AUTOCOLOR;
   }
-  if (style->dwMask & CFM_UNDERLINE)
+  if (mod->dwMask & CFM_UNDERLINE)
   {
-      s->fmt.dwMask |= CFM_UNDERLINETYPE;
-      s->fmt.bUnderlineType = (style->dwEffects & CFM_UNDERLINE) ?
+      fmt.dwMask |= CFM_UNDERLINETYPE;
+      fmt.bUnderlineType = (mod->dwEffects & CFM_UNDERLINE) ?
           CFU_CF1UNDERLINE : CFU_UNDERLINENONE;
   }
-  if (style->dwMask & CFM_BOLD && !(style->dwMask & CFM_WEIGHT))
+  if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT))
   {
-      s->fmt.wWeight = (style->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
-  } else if (style->dwMask & CFM_WEIGHT && !(style->dwMask & CFM_BOLD)) {
-      if (style->wWeight > FW_NORMAL)
-          s->fmt.dwEffects |= CFE_BOLD;
+      fmt.wWeight = (mod->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
+  } else if (mod->dwMask & CFM_WEIGHT && !(mod->dwMask & CFM_BOLD)) {
+      if (mod->wWeight > FW_NORMAL)
+          fmt.dwEffects |= CFE_BOLD;
       else
-          s->fmt.dwEffects &= ~CFE_BOLD;
+          fmt.dwEffects &= ~CFE_BOLD;
+  }
+
+  LIST_FOR_EACH_ENTRY(s, &editor->style_list, ME_Style, entry)
+  {
+      if (!memcmp( &s->fmt, &fmt, sizeof(fmt) ))
+      {
+          TRACE_(richedit_style)("found existing style %p\n", s);
+          ME_AddRefStyle( s );
+          return s;
+      }
   }
+
+  s = ME_MakeStyle( &fmt );
+  if (s)
+      list_add_head( &editor->style_list, &s->entry );
+  TRACE_(richedit_style)("created new style %p\n", s);
   return s;
 }
 
@@ -423,8 +441,9 @@ void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont)
   s->font_cache = NULL;
 }
 
-static void ME_DestroyStyle(ME_Style *s)
+void ME_DestroyStyle(ME_Style *s)
 {
+  list_remove( &s->entry );
   if (s->font_cache)
   {
     release_font_cache( s->font_cache );
@@ -524,7 +543,7 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
     ME_Style *style, *def = editor->pBuffer->pDefaultStyle;
 
     assert(mod->cbSize == sizeof(CHARFORMAT2W));
-    style = ME_ApplyStyle(def, mod);
+    style = ME_ApplyStyle(editor, def, mod);
     def->fmt = style->fmt;
     def->tm = style->tm;
     if (def->font_cache)




More information about the wine-cvs mailing list