• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Kevin Watters, Kevin Ollivier.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "GlyphBuffer.h"
28 #include "GraphicsContext.h"
29 #include "SimpleFontData.h"
30 
31 #include <wx/dc.h>
32 #include <wx/dcgraph.h>
33 #include <wx/defs.h>
34 #include <wx/dcclient.h>
35 #include <wx/gdicmn.h>
36 #include <vector>
37 
38 #if USE(WXGC)
39 #include <cairo.h>
40 #include <assert.h>
41 
42 #include <pango/pango.h>
43 #include <pango/pangocairo.h>
44 
45 // Use cairo-ft if a recent enough Pango version isn't available
46 #if !PANGO_VERSION_CHECK(1,18,0)
47 #include <cairo-ft.h>
48 #include <pango/pangofc-fontmap.h>
49 #endif
50 
51 #endif
52 
53 #include <gtk/gtk.h>
54 
55 namespace WebCore {
56 
57 #if USE(WXGC)
58 static PangoFontMap* g_fontMap;
59 
pangoFontMap()60 PangoFontMap* pangoFontMap()
61 {
62     if (!g_fontMap)
63         g_fontMap = pango_cairo_font_map_get_default();
64 
65     return g_fontMap;
66 }
67 
createPangoFontForFont(const wxFont * wxfont)68 PangoFont* createPangoFontForFont(const wxFont* wxfont)
69 {
70     ASSERT(wxfont && wxfont->Ok());
71 
72     const char* face = wxfont->GetFaceName().mb_str(wxConvUTF8);
73     char const* families[] = {
74         face,
75         0
76     };
77 
78     switch (wxfont->GetFamily()) {
79     case wxFONTFAMILY_ROMAN:
80         families[1] = "serif";
81         break;
82     case wxFONTFAMILY_SWISS:
83         families[1] = "sans";
84         break;
85     case wxFONTFAMILY_MODERN:
86         families[1] = "monospace";
87         break;
88     default:
89         families[1] = "sans";
90     }
91 
92     PangoFontDescription* description = pango_font_description_new();
93     pango_font_description_set_absolute_size(description, wxfont->GetPointSize() * PANGO_SCALE);
94 
95     PangoFont* pangoFont = 0;
96     PangoContext* pangoContext = 0;
97 
98     switch (wxfont->GetWeight()) {
99     case wxFONTWEIGHT_LIGHT:
100         pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
101         break;
102     case wxFONTWEIGHT_NORMAL:
103         pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
104         break;
105     case wxFONTWEIGHT_BOLD:
106         pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
107         break;
108     }
109 
110     switch (wxfont->GetStyle()) {
111     case wxFONTSTYLE_NORMAL:
112         pango_font_description_set_style(description, PANGO_STYLE_NORMAL);
113         break;
114     case wxFONTSTYLE_ITALIC:
115         pango_font_description_set_style(description, PANGO_STYLE_ITALIC);
116         break;
117     case wxFONTSTYLE_SLANT:
118         pango_font_description_set_style(description, PANGO_STYLE_OBLIQUE);
119         break;
120     }
121 
122     PangoFontMap* fontMap = pangoFontMap();
123 
124     pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(fontMap));
125     for (unsigned i = 0; !pangoFont && i < G_N_ELEMENTS(families); i++) {
126         pango_font_description_set_family(description, families[i]);
127         pango_context_set_font_description(pangoContext, description);
128         pangoFont = pango_font_map_load_font(fontMap, pangoContext, description);
129     }
130     pango_font_description_free(description);
131 
132     return pangoFont;
133 }
134 
createScaledFontForFont(const wxFont * wxfont)135 cairo_scaled_font_t* createScaledFontForFont(const wxFont* wxfont)
136 {
137     ASSERT(wxfont && wxfont->Ok());
138 
139     cairo_scaled_font_t* scaledFont = NULL;
140     PangoFont* pangoFont = createPangoFontForFont(wxfont);
141 
142 #if PANGO_VERSION_CHECK(1,18,0)
143     if (pangoFont)
144         scaledFont = cairo_scaled_font_reference(pango_cairo_font_get_scaled_font(PANGO_CAIRO_FONT(pangoFont)));
145 #endif
146 
147     return scaledFont;
148 }
149 
pango_font_get_glyph(PangoFont * font,PangoContext * context,gunichar wc)150 PangoGlyph pango_font_get_glyph(PangoFont* font, PangoContext* context, gunichar wc)
151 {
152     PangoGlyph result = 0;
153     gchar buffer[7];
154 
155     gint  length = g_unichar_to_utf8(wc, buffer);
156     g_return_val_if_fail(length, 0);
157 
158     GList* items = pango_itemize(context, buffer, 0, length, NULL, NULL);
159 
160     if (g_list_length(items) == 1) {
161         PangoItem* item = static_cast<PangoItem*>(items->data);
162         PangoFont* tmpFont = item->analysis.font;
163         item->analysis.font = font;
164 
165         PangoGlyphString* glyphs = pango_glyph_string_new();
166         pango_shape(buffer, length, &item->analysis, glyphs);
167 
168         item->analysis.font = tmpFont;
169 
170         if (glyphs->num_glyphs == 1)
171             result = glyphs->glyphs[0].glyph;
172         else
173             g_warning("didn't get 1 glyph but %d", glyphs->num_glyphs);
174 
175         pango_glyph_string_free(glyphs);
176     }
177 
178     g_list_foreach(items, (GFunc)pango_item_free, NULL);
179     g_list_free(items);
180 
181     return result;
182 }
183 #endif // USE(WXGC)
184 
185 
drawTextWithSpacing(GraphicsContext * graphicsContext,const SimpleFontData * font,const wxColour & color,const GlyphBuffer & glyphBuffer,int from,int numGlyphs,const FloatPoint & point)186 void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point)
187 {
188 #if USE(WXGC)
189     wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext());
190     wxGraphicsContext* gc = dc->GetGraphicsContext();
191     gc->PushState();
192     cairo_t* cr = (cairo_t*)gc->GetNativeContext();
193 
194     wxFont* wxfont = font->getWxFont();
195     PangoFont* pangoFont = createPangoFontForFont(wxfont);
196     PangoFontMap* fontMap = pangoFontMap();
197     PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(fontMap));
198     cairo_scaled_font_t* scaled_font = createScaledFontForFont(wxfont);
199     ASSERT(scaled_font);
200 
201     cairo_glyph_t* glyphs = NULL;
202     glyphs = static_cast<cairo_glyph_t*>(malloc(sizeof(cairo_glyph_t) * numGlyphs));
203 
204     float offset = point.x();
205 
206     for (int i = 0; i < numGlyphs; i++) {
207         glyphs[i].index = pango_font_get_glyph(pangoFont, pangoContext, glyphBuffer.glyphAt(from + i));
208         glyphs[i].x = offset;
209         glyphs[i].y = point.y();
210         offset += glyphBuffer.advanceAt(from + i);
211     }
212 
213     cairo_set_source_rgba(cr, color.Red()/255.0, color.Green()/255.0, color.Blue()/255.0, color.Alpha()/255.0);
214     cairo_set_scaled_font(cr, scaled_font);
215 
216     cairo_show_glyphs(cr, glyphs, numGlyphs);
217 
218     cairo_scaled_font_destroy(scaled_font);
219     gc->PopState();
220 #else
221     wxDC* dc = graphicsContext->platformContext();
222 
223     wxFont* wxfont = font->getWxFont();
224     if (wxfont && wxfont->IsOk())
225         dc->SetFont(*wxfont);
226     dc->SetTextForeground(color);
227 
228     // convert glyphs to wxString
229     GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
230     int offset = point.x();
231     wxString text = wxEmptyString;
232     for (unsigned i = 0; i < numGlyphs; i++) {
233         text = text.Append((wxChar)glyphs[i]);
234         offset += glyphBuffer.advanceAt(from + i);
235     }
236 
237     // the y point is actually the bottom point of the text, turn it into the top
238     float height = font->ascent() - font->descent();
239     wxCoord ypoint = (wxCoord) (point.y() - height);
240 
241     dc->DrawText(text, (wxCoord)point.x(), ypoint);
242 #endif
243 }
244 
245 }
246