Пример #1
0
static void
render_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
             int *n_glyphs, int cluster_offset)
{
  int index;

  index = find_char (font, tone);
  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
  if (index)
    {
      set_glyph_tone (font, glyphs, *n_glyphs, cluster_offset, index);
    }
  else 
    {
      /* fall back : HTONE1(0x302e) => middle-dot, HTONE2(0x302f) => colon */
      index = find_char (font, tone == HTONE1 ? 0x00b7 : 0x003a);
      if (index)
        {
          set_glyph_tone (font, glyphs, *n_glyphs, cluster_offset, index);
        }
      else 
        set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   get_unknown_glyph (font, tone));
    }
  (*n_glyphs)++;
}
Пример #2
0
/* This is a fallback for when we get a tone mark not preceded
 * by a syllable.
 */
static void
render_isolated_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
		      int *n_glyphs, int cluster_offset)
{
#if 0 /* FIXME: what kind of hack is it?  it draws dummy glyphs.  */
  /* Find a base character to render the mark on
   */
  int index = find_char (font, 0x25cc);	/* DOTTED CIRCLE */
  if (!index)
    index = find_char (font, 0x25cb);   /* WHITE CIRCLE, in KSC-5601 */
  if (!index)
    index = find_char (font, ' ');      /* Space */
  if (!index)				/* Unknown glyph box with 0000 in it */
    index = find_char (font, PANGO_GET_UNKNOWN_GLYPH (0));

  /* Add the base character
   */
  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
  (*n_glyphs)++;
#endif

  /* And the tone mark
   */
  render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
}
Пример #3
0
static void
render_basic (PangoFont *font, gunichar wc,
	      PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
{
  int index;

  if (wc == 0xa0)	/* non-break-space */
    wc = 0x20;

  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);

  if (pango_is_zero_width (wc))
    set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GLYPH_EMPTY);
  else
    {
      index = find_char (font, wc);
      if (index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, get_unknown_glyph (font, wc));
    }
  (*n_glyphs)++;
}
Пример #4
0
/* This is a fallback for when we get a tone mark not preceded
 * by a syllable.
 */
static void
render_isolated_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
		      int *n_glyphs, int cluster_offset)
{
  /* Find a base character to render the mark on
   */
  int index = find_char (font, 0x25cc);	/* DOTTED CIRCLE */
  if (!index)
    index = find_char (font, 0x25cb);   /* WHITE CIRCLE, in KSC-5601 */
  if (!index)
    index = find_char (font, ' ');      /* Space */
  if (!index)				/* Unknown glyph box with 0000 in it */
    index = find_char (font, get_unknown_glyph (font, 0));

  /* Add the base character
   */
  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
  (*n_glyphs)++;

  /* And the tone mrak
   */
  render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
}
Пример #5
0
bool set_o(char ar[][SIZE], unsigned int x, unsigned int y) {
    void* ar_p = ar;
    return set_glyph(ar_p, x, y, 'o');
}
Пример #6
0
static void
render_syllable (PangoFont *font, gunichar *text, int length,
		 PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
{
  int n_prev_glyphs = *n_glyphs;
  int index;
  gunichar wc, tone;
  int i, j, composed;

  if (IS_M (text[length - 1]))
    {
      tone = text[length - 1];
      length--;
    }
  else
    tone = 0;

  if (length >= 3 && IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2]))
    composed = 3;
  else if (length >= 2 && IS_L_S(text[0]) && IS_V_S(text[1]))
    composed = 2;
  else
    composed = 0;

  if (composed)
    {
      if (composed == 3)
	wc = S_FROM_LVT(text[0], text[1], text[2]);
      else
	wc = S_FROM_LV(text[0], text[1]);
      index = find_char (font, wc);
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   get_unknown_glyph (font, wc));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      (*n_glyphs)++;
      text += composed;
      length -= composed;
    }

  /* Render the remaining text as uncomposed forms as a fallback.  */
  for (i = 0; i < length; i++)
    {
      int jindex;
      int oldlen;

      if (text[i] == LFILL || text[i] == VFILL)
	continue;

      index = find_char (font, text[i]);
      if (index)
	{
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	  continue;
	}

      /* This font has no glyphs on the Hangul Jamo area!  Find a
	 fallback from the Hangul Compatibility Jamo area.  */
      jindex = text[i] - LBASE;
      oldlen = *n_glyphs;
      for (j = 0; j < 3 && (__jamo_to_ksc5601[jindex][j] != 0); j++)
	{
	  wc = __jamo_to_ksc5601[jindex][j] - KSC_JAMOBASE + UNI_JAMOBASE;
	  index = (wc >= 0x3131) ? find_char (font, wc) : 0;
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  if (!index)
	    {
	      *n_glyphs = oldlen;
	      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	      set_glyph (font, glyphs, *n_glyphs, cluster_offset,
			 get_unknown_glyph (font, text[i]));
	      (*n_glyphs)++;
	      break;
	    }
	  else
	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	}
    }
  if (n_prev_glyphs == *n_glyphs)
    {
      index = find_char (font, 0x3164);
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   get_unknown_glyph (font, index));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      glyphs->log_clusters[*n_glyphs] = cluster_offset;
      (*n_glyphs)++;
    }
  if (tone)
    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
}
Пример #7
0
unsigned char *gks_ft_get_bitmap(int *x, int *y, int *width, int *height,
                                 gks_state_list_t *gkss, const char *text,
                                 int length) {
  FT_Face face;                   /* font face */
  FT_Vector pen;                  /* glyph position */
  FT_BBox bb;                     /* bounding box */
  FT_Vector bearing;              /* individual glyph translation */
  FT_UInt previous;               /* previous glyph index */
  FT_Vector spacing;              /* amount of additional space between glyphs */
  FT_ULong textheight;            /* textheight in FreeType convention */
  FT_Error error;                 /* error code */
  FT_Matrix rotation;             /* text rotation matrix */
  FT_UInt size;                   /* number of pixels of the bitmap */
  FT_String *file;                /* concatenated font path */
  const FT_String *font, *prefix; /* font file name and directory */
  FT_UInt *unicode_string;        /* unicode text string */
  FT_Int halign, valign;          /* alignment */
  FT_Byte *mono_bitmap = NULL;    /* target for rendered text */
  FT_Int num_glyphs;              /* number of glyphs */
  FT_Vector align;
  FT_Bitmap ftbitmap;
  FT_UInt codepoint;
  int i, textfont, dx, dy, value, pos_x, pos_y;
  unsigned int j, k;
  double angle;
  const int windowwidth = *width;
  const int direction = (gkss->txp <= 3 && gkss->txp >= 0 ? gkss->txp : 0);
  const FT_Bool vertical = (direction == GKS_K_TEXT_PATH_DOWN ||
                            direction == GKS_K_TEXT_PATH_UP);
  const FT_String *suffix_type1 = ".afm";

  if (!init) gks_ft_init();

  if (gkss->txal[0] != GKS_K_TEXT_HALIGN_NORMAL) {
    halign = gkss->txal[0];
  } else if (vertical) {
    halign = GKS_K_TEXT_HALIGN_CENTER;
  } else if (direction == GKS_K_TEXT_PATH_LEFT) {
    halign = GKS_K_TEXT_HALIGN_RIGHT;
  } else {
    halign = GKS_K_TEXT_HALIGN_LEFT;
  }
  valign = gkss->txal[1];
  if (valign != GKS_K_TEXT_VALIGN_NORMAL) {
    valign = gkss->txal[1];
  } else {
    valign = GKS_K_TEXT_VALIGN_BASE;
  }

  textfont = abs(gkss->txfont);
  if (textfont >= 101 && textfont <= 131)
    textfont -= 100;
  else if (textfont > 1 && textfont <= 32)
    textfont = map[textfont - 1];
  else
    textfont = 9;

  textfont = textfont - 1;
  font = gks_font_list[textfont];

  if (font_face_cache[textfont] == NULL) {
    prefix = gks_getenv("GKS_FONTPATH");
    if (prefix == NULL) {
      prefix = gks_getenv("GRDIR");
      if (prefix == NULL)
        prefix = GRDIR;
    }
    file = (FT_String *) malloc(strlen(prefix) + 7 + strlen(font) + 4 + 1);
    strcpy(file, prefix);
#ifndef _WIN32
    strcat(file, "/fonts/");
#else
    strcat(file, "\\FONTS\\");
#endif
    strcat(file, font);
    strcat(file, ".pfb");
    error = FT_New_Face(library, file, 0, &face);
    if (error == FT_Err_Unknown_File_Format) {
      gks_perror("unknown file format: %s", file);
      return NULL;
    } else if (error) {
      gks_perror("could not open font file: %s", file);
      return NULL;
    }
    if (strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0) {
      strcpy(file, prefix);
#ifndef _WIN32
      strcat(file, "/fonts/");
#else
      strcat(file, "\\FONTS\\");
#endif
      strcat(file, font);
      strcat(file, suffix_type1);
      FT_Attach_File(face, file);
    }
    free(file);
    font_face_cache[textfont] = face;
  } else {
    face = font_face_cache[textfont];
  }

  num_glyphs = length;
  unicode_string = (FT_UInt *) malloc(length * sizeof(FT_UInt) + 1);
  if (textfont + 1 == 13) {
    symbol_to_unicode((FT_Bytes)text, unicode_string, num_glyphs);
  } else {
    utf_to_unicode((FT_Bytes)text, unicode_string, &num_glyphs);
  }

  textheight = nint(gkss->chh * windowwidth * 64 / caps[textfont]);
  error = FT_Set_Char_Size(face, nint(textheight * gkss->chxp), textheight,
                           72, 72);
  if (error) gks_perror("cannot set text height");

  if (gkss->chup[0] != 0.0 || gkss->chup[1] != 0.0) {
    angle = atan2f(gkss->chup[1], gkss->chup[0]) - M_PI / 2;
    rotation.xx = nint( cosf(angle) * 0x10000L);
    rotation.xy = nint(-sinf(angle) * 0x10000L);
    rotation.yx = nint( sinf(angle) * 0x10000L);
    rotation.yy = nint( cosf(angle) * 0x10000L);
    FT_Set_Transform(face, &rotation, NULL);
  } else {
    FT_Set_Transform(face, NULL, NULL);
  }

  spacing.x = spacing.y = 0;
  if (gkss->chsp != 0.0) {
    error = FT_Load_Glyph(face, FT_Get_Char_Index(face, ' '),
                          vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT);
    if (!error) {
      spacing.x = nint(face->glyph->advance.x * gkss->chsp);
      spacing.y = nint(face->glyph->advance.y * gkss->chsp);
    } else {
      gks_perror("cannot apply character spacing");
    }
  }

  bb.xMin = bb.yMin = LONG_MAX;
  bb.xMax = bb.yMax = LONG_MIN;
  pen.x = pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    bb.xMin = ft_min(bb.xMin, pen.x + bearing.x);
    bb.xMax = ft_max(bb.xMax, pen.x + bearing.x + 64*face->glyph->bitmap.width);
    bb.yMin = ft_min(bb.yMin, pen.y + bearing.y - 64*face->glyph->bitmap.rows);
    bb.yMax = ft_max(bb.yMax, pen.y + bearing.y);

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  *width  = (int)((bb.xMax - bb.xMin) / 64);
  *height = (int)((bb.yMax - bb.yMin) / 64);
  if (bb.xMax <= bb.xMin || bb.yMax <= bb.yMin) {
    gks_perror("invalid bitmap size");
    free(unicode_string);
    return NULL;
  }
  size = *width * *height;
  mono_bitmap = (FT_Byte *) safe_realloc(mono_bitmap, size);
  memset(mono_bitmap, 0, size);

  pen.x = 0;
  pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    bearing.x = bearing.y = 0;
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    pos_x = ( pen.x + bearing.x - bb.xMin) / 64;
    pos_y = (-pen.y - bearing.y + bb.yMax) / 64;
    ftbitmap = face->glyph->bitmap;
    for (j = 0; j < (unsigned int) ftbitmap.rows; j++) {
      for (k = 0; k < (unsigned int) ftbitmap.width; k++) {
        dx = k + pos_x;
        dy = j + pos_y;
        value = mono_bitmap[dy * *width + dx];
        value += ftbitmap.buffer[j * ftbitmap.pitch + k];
        if (value > 255) {
          value = 255;
        }
        mono_bitmap[dy * *width + dx] = value;
      }
    }

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  free(unicode_string);

  /* Alignment */
  if (direction == GKS_K_TEXT_PATH_DOWN) {
    pen.x += spacing.x;
    pen.y += spacing.y;
  } else {
    pen.x -= spacing.x;
    pen.y -= spacing.y;
  }

  align.x = align.y = 0;
  if (valign != GKS_K_TEXT_VALIGN_BASE) {
    align.y = nint(gkss->chh * windowwidth * 64);
    FT_Vector_Transform(&align, &rotation);
    if (valign == GKS_K_TEXT_VALIGN_HALF) {
      align.x = nint(0.5 * align.x);
      align.y = nint(0.5 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_TOP) {
      align.x = nint(1.2 * align.x);
      align.y = nint(1.2 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_BOTTOM) {
      align.x = nint(-0.2 * align.x);
      align.y = nint(-0.2 * align.y);
    }
  }

  if (!vertical && halign != GKS_K_TEXT_HALIGN_LEFT) {
    FT_Vector right;
    right.x = face->glyph->metrics.width + face->glyph->metrics.horiBearingX;
    right.y = 0;
    if (right.x != 0) {
      FT_Vector_Transform(&right, &rotation);
    }
    pen.x += right.x - face->glyph->advance.x;
    pen.y += right.y - face->glyph->advance.y;
    if (halign == GKS_K_TEXT_HALIGN_CENTER) {
      align.x += pen.x / 2;
      align.y += pen.y / 2;
    } else if (halign == GKS_K_TEXT_HALIGN_RIGHT) {
      align.x += pen.x;
      align.y += pen.y;
    }
  }

  *x += (bb.xMin - align.x) / 64;
  *y += (bb.yMin - align.y) / 64;
  return mono_bitmap;
}
Пример #8
0
static void
render_syllable (PangoFont *font, const char *str, int length,
		 PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
{
  int n_prev_glyphs = *n_glyphs;
  int index;
  gunichar wc = 0, tone = 0, text[4];
  int i, j, composed = 0;
  const char *p;

  /* Normalize it only when the entire sequence is equivalent to a
   * precomposed syllable. It's usually better than prefix
   * normalization both for poor-featured fonts and for smart fonts.
   * I have seen no smart font which can render S+T as a syllable
   * form.
   */

  if (length == 3 || length == 4)
    {
      p = str;
      text[0] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[1] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[2] = g_utf8_get_char(p);

      if (length == 4 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
	goto lvt_out;		/* draw the tone mark later */

      if (IS_L_S(text[0]) && IS_V_S(text[1]) &&  IS_T_S(text[2]))
	{
	  composed = 3;
	  wc = S_FROM_LVT(text[0], text[1], text[2]);
	  str = g_utf8_next_char(p);
	  goto normalize_out;
	}
    }
 lvt_out:

  if (length == 2 || length == 3)
    {
      p = str;
      text[0] = g_utf8_get_char(p);
      p = g_utf8_next_char(p);
      text[1] = g_utf8_get_char(p);

      if (length == 3 && !IS_M(g_utf8_get_char(g_utf8_next_char(p))))
	goto lv_out;		/* draw the tone mark later */
      if (IS_L_S(text[0]) && IS_V_S(text[1]))
	{
	  composed = 2;
	  wc = S_FROM_LV(text[0], text[1]);
	  str = g_utf8_next_char(p);
	}
      else if (IS_S(text[0] && !S_HAS_T(text[0]) && IS_T_S(text[1])))
	{
	  composed = 2;
	  wc = text[0] + (text[1] - TBASE);
	  str = g_utf8_next_char(p);
	  goto normalize_out;
	}
    }
 lv_out:
 normalize_out:

  if (composed)
    {
      index = find_char (font, wc);
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   PANGO_GET_UNKNOWN_GLYPH (wc));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      (*n_glyphs)++;
      length -= composed;
    }

  /* Render the remaining text as uncomposed forms as a fallback.  */
  for (i = 0; i < length; i++, str = g_utf8_next_char(str))
    {
      int jindex;
      int oldlen;

      wc = g_utf8_get_char(str);

      if (wc == LFILL || wc == VFILL)
	continue;

      if (IS_M(wc))
	{
	  tone = wc;
	  break;
	}

      if (IS_S(wc))
	{
	  oldlen = *n_glyphs;

	  text[0] = L_FROM_S(wc);
	  text[1] = V_FROM_S(wc);
	  if (S_HAS_T(wc))
	    {
	      text[2] = T_FROM_S(wc);
	      composed = 3;
	    }
	  else
	      composed = 2;

	  for (j = 0; j < composed; j++)
	    {
	      index = find_char (font, text[j]);
	      if (index)
		{
		  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
		  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
		  (*n_glyphs)++;
		}
	      else
		goto decompose_cancel;
	    }

	  continue;

	decompose_cancel:
	  /* The font doesn't have jamos.  Cancel it. */
	  *n_glyphs = oldlen;
	  pango_glyph_string_set_size (glyphs, *n_glyphs);
	}

      index = find_char (font, wc);
      if (index)
	{
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	  continue;
	}
      else if (IS_S(wc))
	{
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		     PANGO_GET_UNKNOWN_GLYPH (wc));
	  (*n_glyphs)++;
	  continue;
	}

      /* This font has no glyphs on the Hangul Jamo area!  Find a
	 fallback from the Hangul Compatibility Jamo area.  */
      jindex = wc - LBASE;
      oldlen = *n_glyphs;
      for (j = 0; j < 3 && (__jamo_to_ksc5601[jindex][j] != 0); j++)
	{
	  wc = __jamo_to_ksc5601[jindex][j] - KSC_JAMOBASE + UNI_JAMOBASE;
	  index = (wc >= 0x3131) ? find_char (font, wc) : 0;
	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	  if (!index)
	    {
	      *n_glyphs = oldlen;
	      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
	      set_glyph (font, glyphs, *n_glyphs, cluster_offset,
			 PANGO_GET_UNKNOWN_GLYPH (text[i]));
	      (*n_glyphs)++;
	      break;
	    }
	  else
	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
	  (*n_glyphs)++;
	}
    }
  if (n_prev_glyphs == *n_glyphs)
    {
      index = find_char (font, 0x3164);	/* U+3164 HANGUL FILLER */
      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
      if (!index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
		   PANGO_GET_UNKNOWN_GLYPH (index));
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      glyphs->log_clusters[*n_glyphs] = cluster_offset;
      (*n_glyphs)++;
    }
  if (tone)
    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
}
Пример #9
0
static void
basic_engine_shape (PangoEngineShape *engine,
                    PangoFont        *font,
                    const char       *text,
                    gint              length,
                    PangoAnalysis    *analysis,
                    PangoGlyphString *glyphs)
{
    int n_chars;
    int i;
    const char *p;

    g_return_if_fail (font != NULL);
    g_return_if_fail (text != NULL);
    g_return_if_fail (length >= 0);
    g_return_if_fail (analysis != NULL);

#ifdef HAVE_USP10_H

    if (have_uniscribe &&
            !text_is_simple (text, length) &&
            uniscribe_shape (font, text, length, analysis, glyphs))
        return;

#endif

    n_chars = g_utf8_strlen (text, length);

    pango_glyph_string_set_size (glyphs, n_chars);

    p = text;
    for (i = 0; i < n_chars; i++)
    {
        gunichar wc;
        gunichar mirrored_ch;
        PangoGlyph index;

        wc = g_utf8_get_char (p);

        if (analysis->level % 2)
            if (pango_get_mirror_char (wc, &mirrored_ch))
                wc = mirrored_ch;

        if (wc == 0xa0)	/* non-break-space */
            wc = 0x20;

        if (pango_is_zero_width (wc))
        {
            set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
        }
        else
        {
            index = find_char (font, wc);
            if (index)
            {
                set_glyph (font, glyphs, i, p - text, index);

                if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
                {
                    if (i > 0)
                    {
                        PangoRectangle logical_rect, ink_rect;

                        glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
                                                                glyphs->glyphs[i].geometry.width);
                        glyphs->glyphs[i-1].geometry.width = 0;
                        glyphs->log_clusters[i] = glyphs->log_clusters[i-1];

                        /* Some heuristics to try to guess how overstrike glyphs are
                         * done and compensate
                         */
                        /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */
                        pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
                        if (logical_rect.width == 0 && ink_rect.x == 0)
                            glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
                    }
                }
            }
            else
                set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc));
        }

        p = g_utf8_next_char (p);
    }

    /* Simple bidi support... may have separate modules later */

    if (analysis->level % 2)
    {
        int start, end;

        /* Swap all glyphs */
        swap_range (glyphs, 0, n_chars);

        /* Now reorder glyphs within each cluster back to LTR */
        for (start = 0; start < n_chars;)
        {
            end = start;
            while (end < n_chars &&
                    glyphs->log_clusters[end] == glyphs->log_clusters[start])
                end++;

            swap_range (glyphs, start, end);
            start = end;
        }
    }
}
Пример #10
0
static void
basic_engine_shape (PangoEngineShape    *engine,
		    PangoFont           *font,
		    const char          *text,
		    gint                 length,
		    const PangoAnalysis *analysis,
		    PangoGlyphString    *glyphs)
{
  const char *p;
  char *copy;
  CTLineRef line;
  CFStringRef cstr;
  CFDictionaryRef attributes;
  CFAttributedStringRef attstr;
  PangoCoreTextFont *cfont = PANGO_CORE_TEXT_FONT (font);
  PangoCoverage *coverage;
  CFArrayRef runs;
  CTRunRef run;
  CTRunStatus run_status;
  CFIndex i, glyph_count;
  const CGGlyph *cgglyphs;

  CFTypeRef keys[] = {
      (CFTypeRef) kCTFontAttributeName
  };

  CFTypeRef values[] = {
      pango_core_text_font_get_ctfont (cfont)
  };

  attributes = CFDictionaryCreate (kCFAllocatorDefault,
                                   (const void **)keys,
                                   (const void **)values,
                                   1,
                                   &kCFCopyStringDictionaryKeyCallBacks,
                                   &kCFTypeDictionaryValueCallBacks);

  copy = g_strndup (text, length + 1);
  copy[length] = 0;

  cstr = CFStringCreateWithCString (kCFAllocatorDefault, copy,
                                    kCFStringEncodingUTF8);
  g_free (copy);

  attstr = CFAttributedStringCreate (kCFAllocatorDefault,
                                     cstr,
                                     attributes);

  line = CTLineCreateWithAttributedString (attstr);

  runs = CTLineGetGlyphRuns (line);

  /* Since Pango divides things into runs already, we assume there is
   * only a single run in this line.
   */
  run = CFArrayGetValueAtIndex (runs, 0);
  run_status = CTRunGetStatus (run);
  glyph_count = CTRunGetGlyphCount (run);
  cgglyphs = CTRunGetGlyphsPtr (run);

  p = text;
  pango_glyph_string_set_size (glyphs, glyph_count);
  coverage = pango_font_get_coverage (PANGO_FONT (cfont),
                                      analysis->language);

  for (i = 0; i < glyph_count; i++)
    {
      CFIndex real_i, prev_i;
      gunichar wc;
      gunichar mirrored_ch;

      wc = g_utf8_get_char (p);

      if (analysis->level % 2)
	if (pango_get_mirror_char (wc, &mirrored_ch))
	  wc = mirrored_ch;

      if (run_status & kCTRunStatusRightToLeft)
        {
          real_i = glyph_count - i - 1;
          prev_i = real_i + 1;
        }
      else
        {
          real_i = i;
          prev_i = real_i - 1;
        }

      if (wc == 0xa0)	/* non-break-space */
	wc = 0x20;

      if (pango_is_zero_width (wc))
	{
	  set_glyph (font, glyphs, real_i, p - text, PANGO_GLYPH_EMPTY);
	}
      else
	{
          PangoCoverageLevel result;

          result = pango_coverage_get (coverage, wc);

          if (result != PANGO_COVERAGE_NONE)
            {
              set_glyph (font, glyphs, real_i, p - text, cgglyphs[real_i]);

              if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
                {
                  if (i > 0)
                    {
                      PangoRectangle logical_rect, ink_rect;

                      glyphs->glyphs[real_i].geometry.width = MAX (glyphs->glyphs[prev_i].geometry.width,
                                                                   glyphs->glyphs[prev_i].geometry.width);
                      glyphs->glyphs[prev_i].geometry.width = 0;
                      glyphs->log_clusters[real_i] = glyphs->log_clusters[prev_i];

                      /* Some heuristics to try to guess how overstrike glyphs are
                       * done and compensate
                       */
                      pango_font_get_glyph_extents (font, glyphs->glyphs[real_i].glyph, &ink_rect, &logical_rect);
                      if (logical_rect.width == 0 && ink_rect.x == 0)
                        glyphs->glyphs[real_i].geometry.x_offset = (glyphs->glyphs[real_i].geometry.width - ink_rect.width) / 2;
                    }
                }
            }
          else
            {
              set_glyph (font, glyphs, real_i, p - text,
                         PANGO_GET_UNKNOWN_GLYPH (wc));
            }
        }

      p = g_utf8_next_char (p);
    }

  CFRelease (line);
  CFRelease (attstr);
  CFRelease (cstr);
  CFRelease (attributes);
  pango_coverage_unref (coverage);
}