Git init
[external/pango1.0.git] / modules / basic / basic-atsui.c
1 /* Pango
2  * basic-atsui.c
3  *
4  * Copyright (C) 2005 Imendio AB
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23 #include <glib.h>
24 #include <string.h>
25 #include <Carbon/Carbon.h>
26 #include "pango-engine.h"
27 #include "pango-utils.h"
28 #include "pango-fontmap.h"
29 #include "pangoatsui.h"
30
31 /* No extra fields needed */
32 typedef PangoEngineShape      BasicEngineATSUI;
33 typedef PangoEngineShapeClass BasicEngineATSUIClass ;
34
35 #define SCRIPT_ENGINE_NAME "BasicScriptEngineATSUI"
36 #define RENDER_TYPE PANGO_RENDER_TYPE_ATSUI
37
38 static PangoEngineScriptInfo basic_scripts[] = {
39   { PANGO_SCRIPT_COMMON,   "" }
40 };
41
42 static PangoEngineInfo script_engines[] = {
43   {
44     SCRIPT_ENGINE_NAME,
45     PANGO_ENGINE_TYPE_SHAPE,
46     RENDER_TYPE,
47     basic_scripts, G_N_ELEMENTS(basic_scripts)
48   }
49 };
50
51 static void
52 set_glyph (PangoFont        *font,
53            PangoGlyphString *glyphs,
54            int               i,
55            int               offset,
56            PangoGlyph        glyph)
57 {
58   PangoRectangle logical_rect;
59
60   glyphs->glyphs[i].glyph = G_UNLIKELY (glyph == kATSDeletedGlyphcode) ?
61                             PANGO_GLYPH_EMPTY : glyph;
62
63   glyphs->glyphs[i].geometry.x_offset = 0;
64   glyphs->glyphs[i].geometry.y_offset = 0;
65
66   glyphs->log_clusters[i] = offset;
67   pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
68   glyphs->glyphs[i].geometry.width = logical_rect.width;
69 }
70
71 static void
72 basic_engine_shape (PangoEngineShape    *engine,
73                     PangoFont           *font,
74                     const char          *text,
75                     gint                 length,
76                     const PangoAnalysis *analysis,
77                     PangoGlyphString    *glyphs)
78 {
79   gunichar2 *utf16;
80   long n16;
81   ATSUTextLayout text_layout;
82   ATSLayoutRecord *layout_records;
83   OSStatus err;
84   ItemCount glyph_count;
85   int i;
86   const char *p;
87   PangoATSUIFont *afont = PANGO_ATSUI_FONT (font);
88   ATSUStyle style;
89   CGFontRef fontID;
90   ATSUAttributeTag styleTags[] = { kATSUFontTag };
91   ATSUAttributeValuePtr styleValues[] = { &fontID };
92   ByteCount styleSizes[] = { sizeof (CGFontRef) };
93
94   utf16 = g_utf8_to_utf16 (text, length, NULL, &n16, NULL);
95
96   err = ATSUCreateTextLayout (&text_layout);
97   err = ATSUSetTextPointerLocation (text_layout, utf16, 0, n16, n16);
98
99   err = ATSUCreateStyle(&style);
100   fontID = pango_atsui_font_get_cgfont (afont);
101
102   err = ATSUSetAttributes(style,
103                           sizeof(styleTags) / sizeof(styleTags[0]),
104                           styleTags, styleSizes, styleValues);
105
106   err = ATSUSetRunStyle(text_layout,
107                         style, kATSUFromTextBeginning, kATSUToTextEnd);
108
109   err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout (text_layout, 0,
110                                                        kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
111                                                        (void *)&layout_records,
112                                                        &glyph_count);
113
114   p = text;
115   pango_glyph_string_set_size (glyphs, glyph_count - 1);
116
117   for (i = 0; i < glyph_count - 1; i++)
118     {
119       gunichar wc;
120       gunichar mirrored_ch;
121
122       wc = g_utf8_get_char (p);
123
124       if (analysis->level % 2)
125         if (pango_get_mirror_char (wc, &mirrored_ch))
126           wc = mirrored_ch;
127
128       if (wc == 0xa0)   /* non-break-space */
129         wc = 0x20;
130
131       if (pango_is_zero_width (wc))
132         {
133           set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
134         }
135       else
136         {
137           set_glyph (font, glyphs, i, p - text, layout_records[i].glyphID);
138
139           if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
140             {
141               if (i > 0)
142                 {
143                   PangoRectangle logical_rect, ink_rect;
144
145                   glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
146                                                           glyphs->glyphs[i].geometry.width);
147                   glyphs->glyphs[i-1].geometry.width = 0;
148                   glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
149
150                   /* Some heuristics to try to guess how overstrike glyphs are
151                    * done and compensate
152                    */
153                   pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
154                   if (logical_rect.width == 0 && ink_rect.x == 0)
155                     glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
156                 }
157             }
158         }
159
160       p = g_utf8_next_char (p);
161     }
162
163   ATSUDirectReleaseLayoutDataArrayPtr (NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
164                                        (void *)&layout_records);
165
166   ATSUDisposeStyle (style);
167   ATSUDisposeTextLayout (text_layout);
168
169   g_free (utf16);
170 }
171
172 static void
173 basic_engine_atsui_class_init (PangoEngineShapeClass *class)
174 {
175   class->script_shape = basic_engine_shape;
176 }
177
178 PANGO_ENGINE_SHAPE_DEFINE_TYPE (BasicEngineATSUI, basic_engine_atsui,
179                                 basic_engine_atsui_class_init, NULL);
180
181 void
182 PANGO_MODULE_ENTRY(init) (GTypeModule *module)
183 {
184   basic_engine_atsui_register_type (module);
185 }
186
187 void
188 PANGO_MODULE_ENTRY(exit) (void)
189 {
190 }
191
192 void
193 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
194                           int              *n_engines)
195 {
196   *engines = script_engines;
197   *n_engines = G_N_ELEMENTS (script_engines);
198 }
199
200 PangoEngine *
201 PANGO_MODULE_ENTRY(create) (const char *id)
202 {
203   if (!strcmp (id, SCRIPT_ENGINE_NAME))
204     return g_object_new (basic_engine_atsui_type, NULL);
205   else
206     return NULL;
207 }
208