unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
To: Jason Rumney <jasonr@gnu.org>
Cc: finalpatch <fengli@gmail.com>, emacs-devel@gnu.org
Subject: Re: font-backend
Date: Sat, 23 Feb 2008 11:44:32 +0900	[thread overview]
Message-ID: <wl4pc0mlwv.wl%mituharu@math.s.chiba-u.ac.jp> (raw)
In-Reply-To: <47BF839E.1010402@gnu.org>

>>>>> On Sat, 23 Feb 2008 02:23:26 +0000, Jason Rumney <jasonr@gnu.org> said:

>> I'm developing a font backend driver using Core Text, which is a
>> new framework available from Mac OS X 10.5.  It was slower than
>> Emacs 22 first, but now it shows good performance with caching the
>> results of metrics calculations.

> Yes, it is definitely the metrics calculations that are slowing
> things down on Windows too. I added some code to cache the metrics
> for ASCII characters some time ago, but the problem remains for
> buffers containing many non-ASCII characters.

But it still does get_frame_dc and SelectObject even for the
ASCII-only case.  I think this can be deferred until cache miss
happens.

FWIW, below shows what the Core Text font backend is doing on the
metrics caching.  I assume the height of a valid metrics value is
always nonnegative.


				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

/* The actual structure for Mac Core Text font that can be casted to
   struct font.  */

struct ctfont_info
{
  struct font font;
  CTFontRef ctfont;
  unsigned synthetic_italic_p : 1;
  unsigned synthetic_bold_p : 1;
  short metrics_nrows;
  struct font_metrics **metrics;
};

#define METRICS_NCOLS_PER_ROW	(128)

enum metrics_status
  {
    METRICS_INVALID = -1,  /* metrics entry is invalid */
    METRICS_WIDTH_VALID = -2 /* width is valid but others are invalid */
  };

#define METRICS_STATUS(metrics)	((metrics)->ascent + (metrics)->descent)
#define METRICS_SET_STATUS(metrics, status) \
  ((metrics)->ascent = 0, (metrics)->descent = (status))

static int
ctfont_glyph_extents (font, glyph, metrics)
     struct font *font;
     CGGlyph glyph;
     struct font_metrics *metrics;
{
  struct ctfont_info *ctfont_info = (struct ctfont_info *) font;
  CTFontRef ctfont = ctfont_info->ctfont;
  int row, col;
  struct font_metrics *cache;
  int width;

  row = glyph / METRICS_NCOLS_PER_ROW;
  col = glyph % METRICS_NCOLS_PER_ROW;
  if (row >= ctfont_info->metrics_nrows)
    {
      ctfont_info->metrics =
	xrealloc (ctfont_info->metrics,
		 sizeof (struct font_metrics *) * (row + 1));
      bzero (ctfont_info->metrics + ctfont_info->metrics_nrows,
	     (sizeof (struct font_metrics *)
	      * (row + 1 - ctfont_info->metrics_nrows)));
      ctfont_info->metrics_nrows = row + 1;
    }
  if (ctfont_info->metrics[row] == NULL)
    {
      struct font_metrics *new;
      int i;

      new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
      for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
	METRICS_SET_STATUS (new + i, METRICS_INVALID);
      ctfont_info->metrics[row] = new;
    }
  cache = ctfont_info->metrics[row] + col;

  if (METRICS_STATUS (cache) == METRICS_INVALID)
    {
      cache->width =
	CTFontGetAdvancesForGlyphs (ctfont, kCTFontDefaultOrientation,
				    &glyph, NULL, 1) + 0.5;
      METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
    }
  width = cache->width;

  if (metrics)
    {
      if (METRICS_STATUS (cache) == METRICS_WIDTH_VALID)
	{
	  CGRect bounds;

	  bounds = CTFontGetBoundingRectsForGlyphs (ctfont,
						    kCTFontDefaultOrientation,
						    &glyph, NULL, 1);
	  if (ctfont_info->synthetic_italic_p)
	    bounds = CGRectApplyAffineTransform (bounds, synthetic_italic_atfm);
	  if (ctfont_info->synthetic_bold_p)
	    {
	      CGFloat d = - synthetic_bold_factor * CTFontGetSize (ctfont) / 2;

	      bounds = CGRectInset (bounds, d, d);
	    }
	  bounds = CGRectIntegral (bounds);
	  cache->lbearing = CGRectGetMinX (bounds);
	  cache->rbearing = CGRectGetMaxX (bounds);
	  cache->width = width;
	  cache->ascent = CGRectGetMaxY (bounds);
	  cache->descent = -CGRectGetMinY (bounds);
	}
      *metrics = *cache;
    }

  return width;
}

static int
ctfont_text_extents (font, code, nglyphs, metrics)
     struct font *font;
     unsigned *code;
     int nglyphs;
     struct font_metrics *metrics;
{
  int width, i;

  BLOCK_INPUT;
  width = ctfont_glyph_extents (font, code[0], metrics);
  for (i = 1; i < nglyphs; i++)
    {
      struct font_metrics m;
      int w = ctfont_glyph_extents (font, code[i], metrics ? &m : NULL);

      if (metrics)
	{
	  if (width + m.lbearing < metrics->lbearing)
	    metrics->lbearing = width + m.lbearing;
	  if (width + m.rbearing > metrics->rbearing)
	    metrics->rbearing = width + m.rbearing;
	  if (m.ascent > metrics->ascent)
	    metrics->ascent = m.ascent;
	  if (m.descent > metrics->descent)
	    metrics->descent = m.descent;
	}
      width += w;
    }
  UNBLOCK_INPUT;

  if (metrics)
    metrics->width = width;

  return width;
}




  reply	other threads:[~2008-02-23  2:44 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-15  0:43 23.0.60;show-paren-mode causes abnormal vertical lines on Win32 =?gb18030?B?0+G94A==?=
2008-02-15  9:12 ` 23.0.60; show-paren-mode " Jason Rumney
2008-02-15 14:24   ` Stefan Monnier
2008-02-15 21:44     ` Jason Rumney
2008-02-15 23:02       ` Juanma Barranquero
2008-02-15 23:16         ` Jason Rumney
2008-02-15 23:27           ` Juanma Barranquero
2008-02-15 23:31             ` font-backend [was Re: 23.0.60; show-paren-mode causes abnormal vertical lines on Win32.] Glenn Morris
2008-02-15 23:47               ` font-backend Miles Bader
2008-02-16 13:18                 ` font-backend Eli Zaretskii
2008-02-16 13:27                   ` font-backend Miles Bader
2008-02-16 17:12                   ` font-backend Jason Rumney
2008-02-17  9:29                   ` font-backend Kenichi Handa
2008-02-22 14:00                     ` font-backend finalpatch
2008-02-22 16:43                       ` font-backend Stefan Monnier
2008-02-23  0:15                         ` font-backend Feng Li
2008-02-23  0:25                       ` font-backend YAMAMOTO Mitsuharu
2008-02-23  2:23                         ` font-backend Jason Rumney
2008-02-23  2:44                           ` YAMAMOTO Mitsuharu [this message]
2008-02-24 15:24                             ` font-backend Jason Rumney
2008-02-25 10:03                               ` font-backend finalpatch
2008-02-23  2:28                       ` font-backend Jason Rumney
2008-02-23  2:38                         ` font-backend Feng Li
2008-02-16  3:08           ` 23.0.60; show-paren-mode causes abnormal vertical lines on Win32 Stefan Monnier
2008-02-16  6:01             ` Dan Nicolaescu
2008-02-19 15:51               ` Stefan Monnier
2008-02-19 20:44                 ` Dan Nicolaescu
2008-02-17 13:22             ` Richard Stallman
     [not found]   ` <42b562540802150241wb2d1b66n2f0b50b6c9bbca36@mail.gmail.com>
2008-02-15 23:10     ` Jason Rumney
2008-02-15 23:15       ` Drew Adams
2008-02-17  4:57   ` yu jie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=wl4pc0mlwv.wl%mituharu@math.s.chiba-u.ac.jp \
    --to=mituharu@math.s.chiba-u.ac.jp \
    --cc=emacs-devel@gnu.org \
    --cc=fengli@gmail.com \
    --cc=jasonr@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).