Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 158506 Details for
Bug 129207
Indic language printing from mozilla
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
an updated patch
firefox-1.5.0.12-pango-printing.patch (text/plain), 175.39 KB, created by
Martin Stransky
on 2007-07-04 08:53:18 UTC
(
hide
)
Description:
an updated patch
Filename:
MIME Type:
Creator:
Martin Stransky
Created:
2007-07-04 08:53:18 UTC
Size:
175.39 KB
patch
obsolete
>--- mozilla/config/system-headers.printing 2006-12-19 00:49:21.000000000 +0100 >+++ mozilla/config/system-headers 2007-07-03 15:40:51.000000000 +0200 >@@ -199,6 +199,7 @@ freetype/ftglyph.h > freetype/ftoutln.h > freetype/ttnameid.h > freetype/tttables.h >+freetype/t1tables.h > fribidi/fribidi.h > FSp_fopen.h > fstream.h >@@ -502,6 +503,7 @@ pango/pangofc-font.h > pango/pangofc-fontmap.h > pango/pango-fontmap.h > pango/pango.h >+pango/pangoft2.h > pango/pangoxft.h > pango/pangox.h > pango-types.h >--- mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp.printing 2004-12-17 21:36:28.000000000 +0100 >+++ mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -576,8 +576,10 @@ NS_IMETHODIMP nsDeviceContextGTK::GetDev > // Create a Postscript device context > nsCOMPtr<nsIDeviceContextPS> dcps(do_CreateInstance(kCDeviceContextPS, &rv)); > NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create PS Device context."); >- if (NS_FAILED(rv)) >+ if (NS_FAILED(rv)) { >+ fprintf (stderr, "OK, failed here\n"); > return NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE; >+ } > > rv = dcps->SetSpec(aDevice); > if (NS_FAILED(rv)) >--- /dev/null 2007-07-02 09:48:16.622955810 +0200 >+++ mozilla/gfx/src/gtk/pango-renderer.h 2007-07-03 15:40:51.000000000 +0200 >@@ -0,0 +1,243 @@ >+/* Pango >+ * pango-renderer.h: Base class for rendering >+ * >+ * Copyright (C) 2004, Red Hat, Inc. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, >+ * Boston, MA 02111-1307, USA. >+ */ >+#ifndef __PANGO_RENDERER_H_ >+#define __PANGO_RENDERER_H_ >+ >+#include <pango/pango-layout.h> >+ >+G_BEGIN_DECLS >+ >+#define PANGO_TYPE_RENDERER (pango_renderer_get_type()) >+#define PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_RENDERER, PangoRenderer)) >+#define PANGO_IS_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_RENDERER)) >+#define PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_RENDERER, PangoRendererClass)) >+#define PANGO_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_RENDERER)) >+#define PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_RENDERER, PangoRendererClass)) >+ >+typedef struct _PangoRenderer PangoRenderer; >+typedef struct _PangoRendererClass PangoRendererClass; >+typedef struct _PangoRendererPrivate PangoRendererPrivate; >+ >+/** >+ * PangoRenderPart: >+ * @PANGO_RENDER_PART_FOREGROUND: the text itself >+ * @PANGO_RENDER_PART_BACKGROUND: the area behind the text >+ * @PANGO_RENDER_PART_UNDERLINE: underlines >+ * @PANGO_RENDER_PART_STRIKETHROUGH: strikethrough lines >+ * >+ * #PangoRenderPart defines different items to render for such >+ * purposes as setting colors. >+ * >+ * Since: 1.8 >+ **/ >+/* When extending, note N_RENDER_PARTS #define in pango-renderer.c */ >+typedef enum >+{ >+ PANGO_RENDER_PART_FOREGROUND, >+ PANGO_RENDER_PART_BACKGROUND, >+ PANGO_RENDER_PART_UNDERLINE, >+ PANGO_RENDER_PART_STRIKETHROUGH >+} PangoRenderPart; >+ >+/** >+ * PangoRenderer: >+ * @matrix: the current transformation matrix for the Renderer; may >+ * be %NULL, which should be treated the same as the identity matrix. >+ * >+ * #PangoRenderer is a base class for objects that are used to >+ * render Pango objects such as #PangoGlyphString and >+ * #PangoLayout. >+ * >+ * Since: 1.8 >+ **/ >+struct _PangoRenderer >+{ >+ /*< private >*/ >+ GObject parent_instance; >+ >+ PangoUnderline underline; >+ gboolean strikethrough; >+ int active_count; >+ >+ /*< public >*/ >+ PangoMatrix *matrix; /* May be NULL */ >+ >+ /*< private >*/ >+ PangoRendererPrivate *priv; >+}; >+ >+/** >+ * PangoRendererClass: >+ * @draw_glyphs: draws a #PangoGlyphString >+ * @draw_rectangle: draws a rectangle >+ * @draw_error_underline: draws a squiggly line that approximately >+ * covers the given rectangle in the style of an underline used to >+ * indicate a spelling error. >+ * @draw_shape: draw content for a glyph shaped with #PangoAttrShape. >+ * @x, @y are the coordinates of the left edge of the baseline, >+ * in user coordinates. >+ * @draw_trapezoid: draws a trapezoidal filled area >+ * @draw_glyph: draws a single glyph >+ * @part_changed: do renderer specific processing when rendering >+ * attributes change >+ * @begin: Do renderer-specific initialization before drawing >+ * @end: Do renderer-specific cleanup after drawing >+ * @prepare_run: updates the renderer for a new run >+ * >+ * Class structure for #PangoRenderer. >+ * >+ * Since: 1.8 >+ **/ >+struct _PangoRendererClass >+{ >+ /*< private >*/ >+ GObjectClass parent_class; >+ >+ /* vtable - not signals */ >+ /*< public >*/ >+ >+ /* All of the following have default implementations >+ * and take as coordinates user coordinates in Pango units >+ */ >+ void (*draw_glyphs) (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y); >+ void (*draw_rectangle) (PangoRenderer *renderer, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height); >+ void (*draw_error_underline) (PangoRenderer *renderer, >+ int x, >+ int y, >+ int width, >+ int height); >+ >+ /* Nothing is drawn for shaped glyphs unless this is implemented */ >+ void (*draw_shape) (PangoRenderer *renderer, >+ PangoAttrShape *attr, >+ int x, >+ int y); >+ >+ /* These two must be implemented and take coordinates in >+ * device space as doubles. >+ */ >+ void (*draw_trapezoid) (PangoRenderer *renderer, >+ PangoRenderPart part, >+ double y1_, >+ double x11, >+ double x21, >+ double y2, >+ double x12, >+ double x22); >+ void (*draw_glyph) (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyph glyph, >+ double x, >+ double y); >+ >+ /* Notification of change in rendering attributes >+ */ >+ void (*part_changed) (PangoRenderer *renderer, >+ PangoRenderPart part); >+ >+ /* Paired around drawing operations >+ */ >+ void (*begin) (PangoRenderer *renderer); >+ void (*end) (PangoRenderer *renderer); >+ >+ /* Hooks into the details of layout rendering >+ */ >+ void (*prepare_run) (PangoRenderer *renderer, >+ PangoLayoutRun *run); >+ >+ /*< private >*/ >+ >+ /* Padding for future expansion */ >+ void (*_pango_reserved1) (void); >+ void (*_pango_reserved2) (void); >+ void (*_pango_reserved3) (void); >+ void (*_pango_reserved4) (void); >+}; >+ >+GType pango_renderer_get_type (void); >+ >+void pango_renderer_draw_layout (PangoRenderer *renderer, >+ PangoLayout *layout, >+ int x, >+ int y); >+void pango_renderer_draw_layout_line (PangoRenderer *renderer, >+ PangoLayoutLine *line, >+ int x, >+ int y); >+void pango_renderer_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y); >+void pango_renderer_draw_rectangle (PangoRenderer *renderer, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height); >+void pango_renderer_draw_error_underline (PangoRenderer *renderer, >+ int x, >+ int y, >+ int width, >+ int height); >+void pango_renderer_draw_trapezoid (PangoRenderer *renderer, >+ PangoRenderPart part, >+ double y1_, >+ double x11, >+ double x21, >+ double y2, >+ double x12, >+ double x22); >+void pango_renderer_draw_glyph (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyph glyph, >+ double x, >+ double y); >+ >+void pango_renderer_activate (PangoRenderer *renderer); >+void pango_renderer_deactivate (PangoRenderer *renderer); >+ >+void pango_renderer_part_changed (PangoRenderer *renderer, >+ PangoRenderPart part); >+ >+void pango_renderer_set_color (PangoRenderer *renderer, >+ PangoRenderPart part, >+ const PangoColor *color); >+PangoColor *pango_renderer_get_color (PangoRenderer *renderer, >+ PangoRenderPart part); >+ >+void pango_renderer_set_matrix (PangoRenderer *renderer, >+ const PangoMatrix *matrix); >+G_CONST_RETURN PangoMatrix *pango_renderer_get_matrix (PangoRenderer *renderer); >+ >+G_END_DECLS >+ >+#endif /* __PANGO_RENDERER_H_ */ >+ >--- mozilla/gfx/src/gtk/mozilla-decoder.h.printing 2004-09-22 21:53:45.000000000 +0200 >+++ mozilla/gfx/src/gtk/mozilla-decoder.h 2007-07-03 15:40:51.000000000 +0200 >@@ -39,33 +39,15 @@ > #ifndef _MOZILLA_DECODER_H > #define _MOZILLA_DECODER_H > >-#include <pango/pangofc-decoder.h> >+#include <pango/pango-fontmap.h> > > G_BEGIN_DECLS > >-#define MOZILLA_TYPE_DECODER (mozilla_decoder_get_type()) >-#define MOZILLA_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaDecoder)) >-#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER)) >- >-typedef struct _MozillaDecoder MozillaDecoder; >-typedef struct _MozillaDecoderClass MozillaDecoderClass; >- >-#define MOZILLA_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaDecoderClass)) >-#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER)) >-#define MOZILLA_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderClass)) >- >-struct _MozillaDecoder >-{ >- PangoFcDecoder parent_instance; >-}; >- >-struct _MozillaDecoderClass >-{ >- PangoFcDecoderClass parent_class; >-}; >+#ifdef PSPANGO >+#define mozilla_decoders_init mozilla_decoders_init_ps >+#endif > >-GType mozilla_decoder_get_type (void); >-int mozilla_decoders_init (void); >+int mozilla_decoders_init (PangoFontMap *fontmap); > > G_END_DECLS > >--- /dev/null 2007-07-02 09:48:16.622955810 +0200 >+++ mozilla/gfx/src/gtk/pango-renderer.c 2007-07-03 15:59:36.000000000 +0200 >@@ -0,0 +1,1275 @@ >+/* Pango >+ * pango-renderer.h: Base class for rendering >+ * >+ * Copyright (C) 2004 Red Hat, Inc. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, >+ * Boston, MA 02111-1307, USA. >+ */ >+ >+//#include <config.h> >+#include <stdlib.h> >+ >+#include "pango-renderer.h" >+ >+#ifdef MOZ_ENABLE_PANGO >+#ifndef PANGO_GLYPH_EMPTY >+#define PANGO_GLYPH_EMPTY 0 >+#endif >+#endif >+ >+#define N_RENDER_PARTS 4 >+ >+#define IS_VALID_PART(part) ((guint)part < N_RENDER_PARTS) >+ >+typedef struct _LineState LineState; >+typedef struct _Point Point; >+ >+struct _Point >+{ >+ double x, y; >+}; >+ >+struct _LineState >+{ >+ PangoUnderline underline; >+ PangoRectangle underline_rect; >+ >+ gboolean strikethrough; >+ PangoRectangle strikethrough_rect; >+ >+ int logical_rect_end; >+}; >+ >+struct _PangoRendererPrivate >+{ >+ PangoColor color[N_RENDER_PARTS]; >+ gboolean color_set[N_RENDER_PARTS]; >+ >+ LineState *line_state; >+}; >+ >+static void pango_renderer_finalize (GObject *gobject); >+static void pango_renderer_default_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y); >+static void pango_renderer_default_draw_rectangle (PangoRenderer *renderer, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height); >+static void pango_renderer_default_draw_error_underline (PangoRenderer *renderer, >+ int x, >+ int y, >+ int width, >+ int height); >+static void pango_renderer_default_prepare_run (PangoRenderer *renderer, >+ PangoLayoutRun *run); >+ >+static void pango_renderer_prepare_run (PangoRenderer *renderer, >+ PangoLayoutRun *run); >+ >+static void >+to_device (PangoMatrix *matrix, >+ double x, >+ double y, >+ Point *result) >+{ >+ if (matrix) >+ { >+ result->x = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0; >+ result->y = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0; >+ } >+ else >+ { >+ result->x = x / PANGO_SCALE; >+ result->y = y / PANGO_SCALE; >+ } >+} >+ >+G_DEFINE_ABSTRACT_TYPE (PangoRenderer, pango_renderer, G_TYPE_OBJECT) >+ >+static void >+pango_renderer_class_init (PangoRendererClass *klass) >+{ >+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); >+ >+ klass->draw_glyphs = pango_renderer_default_draw_glyphs; >+ klass->draw_rectangle = pango_renderer_default_draw_rectangle; >+ klass->draw_error_underline = pango_renderer_default_draw_error_underline; >+ klass->prepare_run = pango_renderer_default_prepare_run; >+ >+ gobject_class->finalize = pango_renderer_finalize; >+ >+ g_type_class_add_private (gobject_class, sizeof (PangoRendererPrivate)); >+} >+ >+static void >+pango_renderer_init (PangoRenderer *renderer) >+{ >+ renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer, >+ PANGO_TYPE_RENDERER, >+ PangoRendererPrivate); >+ renderer->matrix = NULL; >+} >+ >+static void >+pango_renderer_finalize (GObject *gobject) >+{ >+ PangoRenderer *renderer = PANGO_RENDERER (gobject); >+ >+ if (renderer->matrix) >+ pango_matrix_free (renderer->matrix); >+} >+ >+/** >+ * pango_glyph_string_get_width: >+ * @glyphs: a #PangoGlyphString >+ * >+ * Computes the logical width of the glyph string as can also be computed >+ * using pango_glyph_string_extents(). However, since this only computes the >+ * width, it's much faster. This is in fact only a convenience function that >+ * computes the sum of geometry.width for each glyph in the @glyphs. >+ * >+ * Return value: the logical width of the glyph string. >+ * >+ * Since: 1.14 >+ */ >+static int >+pango_glyph_string_get_width (PangoGlyphString *glyphs) >+{ >+ int i; >+ int width = 0; >+ >+ for (i = 0; i < glyphs->num_glyphs; i++) >+ width += glyphs->glyphs[i].geometry.width; >+ >+ return width; >+} >+ >+/** >+ * pango_renderer_draw_layout: >+ * @renderer: a #PangoRenderer >+ * @layout: a #PangoLayout >+ * @x: X position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * @y: Y position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * >+ * Draws @layout with the specified #PangoRenderer. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_layout (PangoRenderer *renderer, >+ PangoLayout *layout, >+ int x, >+ int y) >+{ >+ PangoLayoutIter *iter; >+ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (PANGO_IS_LAYOUT (layout)); >+ >+ /* We only change the matrix if the renderer isn't already >+ * active. >+ */ >+ if (!renderer->active_count) >+ { >+ PangoContext *context = pango_layout_get_context (layout); >+ pango_renderer_set_matrix (renderer, >+ pango_context_get_matrix (context)); >+ } >+ >+ pango_renderer_activate (renderer); >+ >+ iter = pango_layout_get_iter (layout); >+ >+ do >+ { >+ PangoRectangle logical_rect; >+ PangoLayoutLine *line; >+ int baseline; >+ >+ line = pango_layout_iter_get_line (iter); >+ >+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); >+ baseline = pango_layout_iter_get_baseline (iter); >+ >+ pango_renderer_draw_layout_line (renderer, >+ line, >+ x + logical_rect.x, >+ y + baseline); >+ } >+ while (pango_layout_iter_next_line (iter)); >+ >+ pango_layout_iter_free (iter); >+ >+ pango_renderer_deactivate (renderer); >+} >+ >+static void >+draw_underline (PangoRenderer *renderer, >+ LineState *state) >+{ >+ PangoRectangle *rect = &state->underline_rect; >+ PangoUnderline underline = state->underline; >+ >+ state->underline = PANGO_UNDERLINE_NONE; >+ >+ switch (underline) >+ { >+ case PANGO_UNDERLINE_NONE: >+ break; >+ case PANGO_UNDERLINE_DOUBLE: >+ pango_renderer_draw_rectangle (renderer, >+ PANGO_RENDER_PART_UNDERLINE, >+ rect->x, >+ rect->y + 2 * rect->height, >+ rect->width, >+ rect->height); >+ /* Fall through */ >+ case PANGO_UNDERLINE_SINGLE: >+ case PANGO_UNDERLINE_LOW: >+ pango_renderer_draw_rectangle (renderer, >+ PANGO_RENDER_PART_UNDERLINE, >+ rect->x, >+ rect->y, >+ rect->width, >+ rect->height); >+ break; >+ case PANGO_UNDERLINE_ERROR: >+ pango_renderer_draw_error_underline (renderer, >+ rect->x, >+ rect->y, >+ rect->width, >+ 3 * rect->height); >+ break; >+ } >+} >+ >+static void >+draw_strikethrough (PangoRenderer *renderer, >+ LineState *state) >+{ >+ PangoRectangle *rect = &state->strikethrough_rect; >+ gboolean strikethrough = state->strikethrough; >+ >+ state->strikethrough = FALSE; >+ >+ if (strikethrough) >+ pango_renderer_draw_rectangle (renderer, >+ PANGO_RENDER_PART_STRIKETHROUGH, >+ rect->x, >+ rect->y, >+ rect->width, >+ rect->height); >+} >+ >+static void >+handle_line_state_change (PangoRenderer *renderer, >+ PangoRenderPart part) >+{ >+ LineState *state = renderer->priv->line_state; >+ if (!state) >+ return; >+ >+ if (part == PANGO_RENDER_PART_UNDERLINE && >+ state->underline != PANGO_UNDERLINE_NONE) >+ { >+ PangoRectangle *rect = &state->underline_rect; >+ >+ rect->width = state->logical_rect_end - rect->x; >+ draw_underline (renderer, state); >+ state->underline = renderer->underline; >+ rect->x = state->logical_rect_end; >+ rect->width = 0; >+ } >+ >+ if (part == PANGO_RENDER_PART_STRIKETHROUGH && >+ state->strikethrough) >+ { >+ PangoRectangle *rect = &state->strikethrough_rect; >+ >+ rect->width = state->logical_rect_end - rect->x; >+ draw_strikethrough (renderer, state); >+ state->strikethrough = renderer->strikethrough; >+ rect->x = state->logical_rect_end; >+ rect->width = 0; >+ } >+} >+ >+static void >+add_underline (PangoRenderer *renderer, >+ LineState *state, >+ PangoFontMetrics *metrics, >+ int base_x, >+ int base_y, >+ PangoRectangle *ink_rect, >+ PangoRectangle *logical_rect) >+{ >+ PangoRectangle *current_rect = &state->underline_rect; >+ PangoRectangle new_rect; >+ >+ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics); >+ int underline_position = pango_font_metrics_get_underline_position (metrics); >+ >+ new_rect.x = base_x + logical_rect->x; >+ new_rect.width = logical_rect->width; >+ new_rect.height = underline_thickness; >+ new_rect.y = base_y; >+ >+ switch (renderer->underline) >+ { >+ case PANGO_UNDERLINE_NONE: >+ g_assert_not_reached (); >+ break; >+ case PANGO_UNDERLINE_SINGLE: >+ case PANGO_UNDERLINE_DOUBLE: >+ case PANGO_UNDERLINE_ERROR: >+ new_rect.y -= underline_position; >+ break; >+ case PANGO_UNDERLINE_LOW: >+ new_rect.y += ink_rect->y + ink_rect->height + underline_thickness; >+ break; >+ } >+ >+ if (renderer->underline == state->underline && >+ new_rect.y == current_rect->y && >+ new_rect.height == current_rect->height) >+ { >+ current_rect->width = new_rect.x + new_rect.width - current_rect->x; >+ } >+ else >+ { >+ draw_underline (renderer, state); >+ >+ *current_rect = new_rect; >+ state->underline = renderer->underline; >+ } >+} >+ >+static void >+add_strikethrough (PangoRenderer *renderer, >+ LineState *state, >+ PangoFontMetrics *metrics, >+ int base_x, >+ int base_y, >+ PangoRectangle *ink_rect, >+ PangoRectangle *logical_rect) >+{ >+ PangoRectangle *current_rect = &state->strikethrough_rect; >+ PangoRectangle new_rect; >+ >+ int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); >+ int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); >+ >+ new_rect.x = base_x + logical_rect->x; >+ new_rect.width = logical_rect->width; >+ new_rect.y = base_y - strikethrough_position; >+ new_rect.height = strikethrough_thickness; >+ >+ if (state->strikethrough && >+ new_rect.y == current_rect->y && >+ new_rect.height == current_rect->height) >+ { >+ current_rect->width = new_rect.x + new_rect.width - current_rect->x; >+ } >+ else >+ { >+ draw_strikethrough (renderer, state); >+ >+ *current_rect = new_rect; >+ state->strikethrough = TRUE; >+ } >+} >+ >+static void >+get_item_properties (PangoItem *item, >+ gint *rise, >+ PangoAttrShape **shape_attr) >+{ >+ GSList *l; >+ >+ if (rise) >+ *rise = 0; >+ >+ if (shape_attr) >+ *shape_attr = NULL; >+ >+ for (l = item->analysis.extra_attrs; l; l = l->next) >+ { >+ PangoAttribute *attr = l->data; >+ >+ switch (attr->klass->type) >+ { >+ case PANGO_ATTR_SHAPE: >+ if (shape_attr) >+ *shape_attr = (PangoAttrShape *)attr; >+ break; >+ >+ case PANGO_ATTR_RISE: >+ if (rise) >+ *rise = ((PangoAttrInt *)attr)->value; >+ break; >+ >+ default: >+ break; >+ } >+ } >+} >+ >+static void >+draw_shaped_glyphs (PangoRenderer *renderer, >+ PangoGlyphString *glyphs, >+ PangoAttrShape *attr, >+ int x, >+ int y) >+{ >+ PangoRendererClass *class = PANGO_RENDERER_GET_CLASS (renderer); >+ int i; >+ >+ if (!class->draw_shape) >+ return; >+ >+ for (i = 0; i < glyphs->num_glyphs; i++) >+ { >+ PangoGlyphInfo *gi = &glyphs->glyphs[i]; >+ >+ class->draw_shape (renderer, attr, x, y); >+ >+ x += gi->geometry.width; >+ } >+} >+ >+/** >+ * pango_renderer_draw_layout_line: >+ * @renderer: a #PangoRenderer >+ * @line: a #PangoLayoutLine >+ * @x: X position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * @y: Y position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * >+ * Draws @line with the specified #PangoRenderer. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_layout_line (PangoRenderer *renderer, >+ PangoLayoutLine *line, >+ int x, >+ int y) >+{ >+ int x_off = 0; >+ int glyph_string_width; >+ LineState state; >+ GSList *l; >+ gboolean got_overall = FALSE; >+ PangoRectangle overall_rect; >+ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ >+ /* We only change the matrix if the renderer isn't already >+ * active. >+ */ >+ if (!renderer->active_count) >+ { >+ PangoContext *context = pango_layout_get_context (line->layout); >+ pango_renderer_set_matrix (renderer, >+ pango_context_get_matrix (context)); >+ } >+ >+ pango_renderer_activate (renderer); >+ >+ renderer->priv->line_state = &state; >+ >+ state.underline = PANGO_UNDERLINE_NONE; >+ state.strikethrough = FALSE; >+ >+ for (l = line->runs; l; l = l->next) >+ { >+ PangoFontMetrics *metrics; >+ gint rise; >+ PangoLayoutRun *run = l->data; >+ PangoAttrShape *shape_attr; >+ PangoRectangle ink_rect, logical_rect; >+ >+ pango_renderer_prepare_run (renderer, run); >+ >+ get_item_properties (run->item, &rise, &shape_attr); >+ >+ if (shape_attr) >+ { >+ ink_rect = shape_attr->ink_rect; >+ logical_rect = shape_attr->logical_rect; >+ glyph_string_width = shape_attr->logical_rect.width; >+ } >+ else >+ { >+ if (renderer->underline != PANGO_UNDERLINE_NONE || >+ renderer->strikethrough) >+ { >+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font, >+ &ink_rect, &logical_rect); >+ glyph_string_width = logical_rect.width; >+ } >+ else >+ glyph_string_width = pango_glyph_string_get_width (run->glyphs); >+ } >+ >+ state.logical_rect_end = x + x_off + glyph_string_width; >+ >+ if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND]) >+ { >+ if (!got_overall) >+ { >+ pango_layout_line_get_extents (line, NULL, &overall_rect); >+ got_overall = TRUE; >+ } >+ >+ pango_renderer_draw_rectangle (renderer, >+ PANGO_RENDER_PART_BACKGROUND, >+ x + x_off, >+ y + overall_rect.y, >+ glyph_string_width, >+ overall_rect.height); >+ } >+ >+ if (shape_attr) >+ { >+ draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - rise); >+ } >+ else >+ { >+ pango_renderer_draw_glyphs (renderer, >+ run->item->analysis.font, run->glyphs, >+ x + x_off, y - rise); >+ } >+ >+ if (renderer->underline != PANGO_UNDERLINE_NONE || >+ renderer->strikethrough) >+ { >+ metrics = pango_font_get_metrics (run->item->analysis.font, >+ run->item->analysis.language); >+ >+ if (renderer->underline != PANGO_UNDERLINE_NONE) >+ add_underline (renderer, &state,metrics, >+ x + x_off, y - rise, >+ &ink_rect, &logical_rect); >+ >+ if (renderer->strikethrough) >+ add_strikethrough (renderer, &state, metrics, >+ x + x_off, y - rise, >+ &ink_rect, &logical_rect); >+ >+ pango_font_metrics_unref (metrics); >+ } >+ >+ if (renderer->underline == PANGO_UNDERLINE_NONE && >+ state.underline != PANGO_UNDERLINE_NONE) >+ draw_underline (renderer, &state); >+ >+ if (!renderer->strikethrough && state.strikethrough) >+ draw_strikethrough (renderer, &state); >+ >+ x_off += glyph_string_width; >+ } >+ >+ /* Finish off any remaining underlines >+ */ >+ draw_underline (renderer, &state); >+ draw_strikethrough (renderer, &state); >+ >+ renderer->priv->line_state = NULL; >+ >+ pango_renderer_deactivate (renderer); >+} >+ >+/** >+ * pango_renderer_draw_glyphs: >+ * @renderer: a #PangoRenderer >+ * @font: a #PangoFont >+ * @glyphs: a #PangoGlyphString >+ * @x: X position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * @y: Y position of left edge of baseline, in user space coordinates >+ * in Pango units. >+ * >+ * Draws the glyphs in @glyphs with the specified #PangoRenderer. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ >+ pango_renderer_activate (renderer); >+ >+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyphs (renderer, font, glyphs, x, y); >+ >+ pango_renderer_deactivate (renderer); >+} >+ >+static void >+pango_renderer_default_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y) >+{ >+ int i; >+ int x_position = 0; >+ >+ for (i = 0; i < glyphs->num_glyphs; i++) >+ { >+ PangoGlyphInfo *gi = &glyphs->glyphs[i]; >+ Point p; >+ >+ to_device (renderer->matrix, >+ x + x_position + gi->geometry.x_offset, >+ y + gi->geometry.y_offset, >+ &p); >+ >+ pango_renderer_draw_glyph (renderer, font, gi->glyph, p.x, p.y); >+ >+ x_position += gi->geometry.width; >+ } >+} >+ >+/** >+ * pango_renderer_draw_rectangle: >+ * @renderer: a #PangoRenderer >+ * @part: type of object this rectangle is part of >+ * @x: X position at which to draw rectangle, in user space coordinates in Pango units >+ * @y: Y position at which to draw rectangle, in user space coordinates in Pango units >+ * @width: width of rectangle in Pango units in user space coordinates >+ * @height: height of rectangle in Pango units in user space coordinates >+ * >+ * Draws an axis-aligned rectangle in user space coordinates with the >+ * specified #PangoRenderer. >+ * >+ * This should be called while @renderer is already active. Use >+ * pango_renderer_activate() to activate a renderer. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_rectangle (PangoRenderer *renderer, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (IS_VALID_PART (part)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ PANGO_RENDERER_GET_CLASS (renderer)->draw_rectangle (renderer, part, x, y, width, height); >+} >+ >+static int >+compare_points (const void *a, >+ const void *b) >+{ >+ const Point *pa = a; >+ const Point *pb = b; >+ >+ if (pa->y < pb->y) >+ return -1; >+ else if (pa->y > pb->y) >+ return 1; >+ else if (pa->x < pb->x) >+ return -1; >+ else if (pa->x > pb->x) >+ return 1; >+ else >+ return 0; >+} >+ >+static void >+draw_rectangle (PangoRenderer *renderer, >+ PangoMatrix *matrix, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height) >+{ >+ Point points[4]; >+ >+ /* Convert the points to device coordinates, and sort >+ * in ascending Y order. (Ordering by X for ties) >+ */ >+ to_device (matrix, x, y, &points[0]); >+ to_device (matrix, x + width, y, &points[1]); >+ to_device (matrix, x, y + height, &points[2]); >+ to_device (matrix, x + width, y + height, &points[3]); >+ >+ qsort (points, 4, sizeof (Point), compare_points); >+ >+ /* There are essentially three cases. (There is a fourth >+ * case where trapezoid B is degenerate and we just have >+ * two triangles, but we don't need to handle it separately.) >+ * >+ * 1 2 3 >+ * >+ * ______ /\ /\ >+ * / / /A \ /A \ >+ * / B / /____\ /____\ >+ * /_____/ / B / \ B \ >+ * /_____/ \_____\ >+ * \ C / \ C / >+ * \ / \ / >+ * \/ \/ >+ */ >+ if (points[0].y == points[1].y) >+ { >+ /* Case 1 (pure shear) */ >+ pango_renderer_draw_trapezoid (renderer, part, /* B */ >+ points[0].y, points[0].x, points[1].x, >+ points[2].y, points[2].x, points[3].x); >+ } >+ else if (points[1].x < points[2].x) >+ { >+ /* Case 2 */ >+ double tmp_width = ((points[2].x - points[0].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y); >+ double base_width = tmp_width + points[0].x - points[1].x; >+ >+ pango_renderer_draw_trapezoid (renderer, part, /* A */ >+ points[0].y, points[0].x, points[0].x, >+ points[1].y, points[1].x, points[1].x + base_width); >+ pango_renderer_draw_trapezoid (renderer, part, /* B */ >+ points[1].y, points[1].x, points[1].x + base_width, >+ points[2].y, points[2].x - base_width, points[2].x); >+ pango_renderer_draw_trapezoid (renderer, part, /* C */ >+ points[2].y, points[2].x - base_width, points[2].x, >+ points[3].y, points[3].x, points[3].x); >+ } >+ else >+ { >+ /* case 3 */ >+ double tmp_width = ((points[0].x - points[2].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y); >+ double base_width = tmp_width + points[1].x - points[0].x; >+ >+ pango_renderer_draw_trapezoid (renderer, part, /* A */ >+ points[0].y, points[0].x, points[0].x, >+ points[1].y, points[1].x - base_width, points[1].x); >+ pango_renderer_draw_trapezoid (renderer, part, /* B */ >+ points[1].y, points[1].x - base_width, points[1].x, >+ points[2].y, points[2].x, points[2].x + base_width); >+ pango_renderer_draw_trapezoid (renderer, part, /* C */ >+ points[2].y, points[2].x, points[2].x + base_width, >+ points[3].y, points[3].x, points[3].x); >+ } >+} >+ >+static void >+pango_renderer_default_draw_rectangle (PangoRenderer *renderer, >+ PangoRenderPart part, >+ int x, >+ int y, >+ int width, >+ int height) >+{ >+ draw_rectangle (renderer, renderer->matrix, part, x, y, width, height); >+} >+ >+/** >+ * pango_renderer_draw_error_underline: >+ * @renderer: a #PangoRenderer >+ * @x: X coordinate of underline, in Pango units in user coordinate system >+ * @y: Y coordinate of underline, in Pango units in user coordinate system >+ * @width: width of underline, in Pango units in user coordinate system >+ * @height: height of underline, in Pango units in user coordinate system >+ * >+ * Draw a squiggly line that approximately covers the given rectangle >+ * in the style of an underline used to indicate a spelling error. >+ * (The width of the underline is rounded to an integer number >+ * of up/down segments and the resulting rectangle is centered >+ * in the original rectangle) >+ * >+ * This should be called while @renderer is already active. Use >+ * pango_renderer_activate() to activate a renderer. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_error_underline (PangoRenderer *renderer, >+ int x, >+ int y, >+ int width, >+ int height) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ PANGO_RENDERER_GET_CLASS (renderer)->draw_error_underline (renderer, x, y, width, height); >+} >+ >+/* We are drawing an error underline that looks like one of: >+ * >+ * /\ /\ /\ /\ /\ - >+ * / \ / \ / \ / \ / \ | >+ * \ \ /\ \ / / \ \ /\ \ | >+ * \ \/B \ \/ C / \ \/B \ \ | height = HEIGHT_SQUARES * square >+ * \ A \ /\ A \ / \ A \ /\ A \ | >+ * \ \/ \ \/ \ \/ \ \ | >+ * \ / \ / \ / \ / | >+ * \/ \/ \/ \/ - >+ * |---| >+ * unit_width = (HEIGHT_SQUARES - 1) * square >+ * >+ * To do this conveniently, we work in a coordinate system where A,B,C >+ * are axis aligned rectangles. (If fonts were square, the diagrams >+ * would be clearer) >+ * >+ * (0,0) >+ * /\ /\ >+ * / \ / \ >+ * /\ /\ /\ / >+ * / \/ \/ \/ >+ * / \ /\ / >+ * Y axis \/ \/ >+ * \ /\ >+ * \/ \ >+ * \ X axis >+ * >+ * Note that the long side in this coordinate system is HEIGHT_SQUARES + 1 >+ * units long >+ * >+ * The diagrams above are shown with HEIGHT_SQUARES an integer, but >+ * that is actually incidental; the value 2.5 below seems better than >+ * either HEIGHT_SQUARES=3 (a little long and skinny) or >+ * HEIGHT_SQUARES=2 (a bit short and stubby) >+ */ >+ >+#define HEIGHT_SQUARES 2.5 >+ >+static void >+get_total_matrix (PangoMatrix *total, >+ const PangoMatrix *global, >+ int x, >+ int y, >+ int square) >+{ >+ PangoMatrix local; >+ gdouble scale = 0.5 * square; >+ >+ /* The local matrix translates from the axis aligned coordinate system >+ * to the original user space coordinate system. >+ */ >+ local.xx = scale; >+ local.xy = - scale; >+ local.yx = scale; >+ local.yy = scale; >+ local.x0 = 0; >+ local.y0 = 0; >+ >+ *total = *global; >+ pango_matrix_concat (total, &local); >+ >+ total->x0 = (global->xx * x + global->xy * y) / PANGO_SCALE + global->x0; >+ total->y0 = (global->yx * x + global->yy * y) / PANGO_SCALE + global->y0; >+} >+ >+static void >+pango_renderer_default_draw_error_underline (PangoRenderer *renderer, >+ int x, >+ int y, >+ int width, >+ int height) >+{ >+ int square = height / HEIGHT_SQUARES; >+ int unit_width = (HEIGHT_SQUARES - 1) * square; >+ int width_units = (width + unit_width / 2) / unit_width; >+ static const PangoMatrix identity = PANGO_MATRIX_INIT; >+ const PangoMatrix *matrix; >+ >+ x += (width - width_units * unit_width) / 2; >+ width = width_units * unit_width; >+ >+ if (renderer->matrix) >+ matrix = renderer->matrix; >+ else >+ matrix = &identity; >+ >+ while (TRUE) >+ { >+ PangoMatrix total; >+ get_total_matrix (&total, matrix, x, y, square); >+ >+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* A */ >+ 0, 0, >+ HEIGHT_SQUARES * 2 - 1, 1); >+ >+ if (width_units > 2) >+ { >+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* B */ >+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 3), >+ 1, HEIGHT_SQUARES * 2 - 3); >+ width_units -= 2; >+ x += unit_width * 2; >+ } >+ else if (width_units == 2) >+ { >+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* C */ >+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 2), >+ 1, HEIGHT_SQUARES * 2 - 2); >+ break; >+ } >+ else >+ break; >+ } >+} >+ >+/** >+ * pango_renderer_draw_trapezoid: >+ * @renderer: a #PangoRenderer >+ * @part: type of object this trapezoid is part of >+ * @y1_: Y coordinate of top of trapezoid >+ * @x11: X coordinate of left end of top of trapezoid >+ * @x21: X coordinate of right end of top of trapezoid >+ * @y2: Y coordinate of bottom of trapezoid >+ * @x12: X coordinate of left end of bottom of trapezoid >+ * @x22: X coordinate of right end of bottom of trapezoid >+ * >+ * Draws a trapezoid with the parallel sides aligned with the X axis >+ * using the given #PangoRenderer; coordinates are in device space. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_trapezoid (PangoRenderer *renderer, >+ PangoRenderPart part, >+ double y1_, >+ double x11, >+ double x21, >+ double y2, >+ double x12, >+ double x22) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ if (PANGO_RENDERER_GET_CLASS (renderer)->draw_trapezoid) >+ PANGO_RENDERER_GET_CLASS (renderer)->draw_trapezoid (renderer, part, >+ y1_, x11, x21, >+ y2, x12, x22); >+} >+ >+/** >+ * pango_renderer_draw_glyph: >+ * @renderer: a #PangoRenderer >+ * @font: a #PangoFont >+ * @glyph: the glyph index of a single glyph >+ * @x: X coordinate of left edge of baseline of glyph >+ * @y: Y coordinate of left edge of baseline of glyph >+ * >+ * Draws a single glyph with coordinates in device space. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_draw_glyph (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyph glyph, >+ double x, >+ double y) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ if (glyph == PANGO_GLYPH_EMPTY) /* glyph PANGO_GLYPH_EMPTY never renders */ >+ return; >+ >+ if (PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph) >+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph (renderer, font, glyph, x, y); >+} >+ >+/** >+ * pango_renderer_activate: >+ * @renderer: a #PangoRenderer >+ * >+ * Does initial setup before rendering operations on @renderer. >+ * pango_renderer_deactivate() should be called when done drawing. >+ * Calls such as pango_renderer_draw_layout() automatically >+ * activate the layout before drawing on it. Calls to >+ * pango_renderer_activate() and pango_renderer_deactivate() can >+ * be nested and the renderer will only be initialized and >+ * deinitialized once. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_activate (PangoRenderer *renderer) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ >+ renderer->active_count++; >+ if (renderer->active_count == 1) >+ { >+ if (PANGO_RENDERER_GET_CLASS (renderer)->begin) >+ PANGO_RENDERER_GET_CLASS (renderer)->begin (renderer); >+ } >+} >+ >+/** >+ * pango_renderer_deactivate: >+ * @renderer: a #PangoRenderer >+ * >+ * Cleans up after rendering operations on @renderer. See >+ * docs for pango_renderer_activate(). >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_deactivate (PangoRenderer *renderer) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ if (renderer->active_count == 1) >+ { >+ if (PANGO_RENDERER_GET_CLASS (renderer)->end) >+ PANGO_RENDERER_GET_CLASS (renderer)->end (renderer); >+ } >+ renderer->active_count--; >+} >+ >+/** >+ * pango_renderer_set_color: >+ * @renderer: a #PangoRenderer >+ * @part: the part to change the color of >+ * @color: the new color or %NULL to unset the current color >+ * >+ * Sets the color for part of the rendering. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_set_color (PangoRenderer *renderer, >+ PangoRenderPart part, >+ const PangoColor *color) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (IS_VALID_PART (part)); >+ >+ if ((!color && !renderer->priv->color_set[part]) || >+ (color && renderer->priv->color_set[part] && >+ renderer->priv->color[part].red == color->red && >+ renderer->priv->color[part].green == color->green && >+ renderer->priv->color[part].blue == color->blue)) >+ return; >+ >+ pango_renderer_part_changed (renderer, part); >+ >+ if (color) >+ { >+ renderer->priv->color_set[part] = TRUE; >+ renderer->priv->color[part] = *color; >+ } >+ else >+ { >+ renderer->priv->color_set[part] = FALSE; >+ } >+} >+ >+/** >+ * pango_renderer_get_color: >+ * @renderer: a #PangoRenderer >+ * @part: the part to get the color for >+ * >+ * Gets the current rendering color for the specified part. >+ * >+ * Return value: the color for the specified part, or %NULL >+ * if it hasn't been set and should be inherited from the >+ * environment. >+ * >+ * Since: 1.8 >+ **/ >+PangoColor * >+pango_renderer_get_color (PangoRenderer *renderer, >+ PangoRenderPart part) >+{ >+ g_return_val_if_fail (PANGO_IS_RENDERER (renderer), NULL); >+ g_return_val_if_fail (IS_VALID_PART (part), NULL); >+ >+ if (renderer->priv->color_set[part]) >+ return &renderer->priv->color[part]; >+ else >+ return NULL; >+} >+ >+/** >+ * pango_renderer_part_changed: >+ * @renderer: a #PangoRenderer >+ * @part: the part for which rendering has changed. >+ * >+ * Informs Pango that the way that the rendering is done >+ * for @part has changed in a way that would prevent multiple >+ * pieces being joined together into one drawing call. For >+ * instance, if a subclass of #PangoRenderer was to add a stipple >+ * option for drawing underlines, it needs to call >+ * >+ * <informalexample><programlisting> >+ * pango_renderer_part_changed (render, PANGO_RENDER_PART_UNDERLINE); >+ * </programlisting></informalexample> >+ * >+ * When the stipple changes or underlines with different stipples >+ * might be joined together. Pango automatically calls this for >+ * changes to colors. (See pango_renderer_set_color()) >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_part_changed (PangoRenderer *renderer, >+ PangoRenderPart part) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ g_return_if_fail (IS_VALID_PART (part)); >+ g_return_if_fail (renderer->active_count > 0); >+ >+ handle_line_state_change (renderer, part); >+ >+ if (PANGO_RENDERER_GET_CLASS (renderer)->part_changed) >+ PANGO_RENDERER_GET_CLASS (renderer)->part_changed (renderer, part); >+} >+ >+/** >+ * pango_renderer_prepare_run: >+ * @renderer: a #PangoRenderer >+ * @run: a #PangoLayoutRun >+ * >+ * Set up the state of the #PangoRenderer for rendering @run. >+ * >+ * Since: 1.8 >+ **/ >+static void >+pango_renderer_prepare_run (PangoRenderer *renderer, >+ PangoLayoutRun *run) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ >+ PANGO_RENDERER_GET_CLASS (renderer)->prepare_run (renderer, run); >+} >+ >+static void >+pango_renderer_default_prepare_run (PangoRenderer *renderer, >+ PangoLayoutRun *run) >+{ >+ PangoColor *fg_color = NULL; >+ PangoColor *bg_color = NULL; >+ PangoColor *underline_color = NULL; >+ PangoColor *strikethrough_color = NULL; >+ GSList *l; >+ >+ renderer->underline = PANGO_UNDERLINE_NONE; >+ renderer->strikethrough = FALSE; >+ >+ for (l = run->item->analysis.extra_attrs; l; l = l->next) >+ { >+ PangoAttribute *attr = l->data; >+ >+ switch (attr->klass->type) >+ { >+ case PANGO_ATTR_UNDERLINE: >+ renderer->underline = ((PangoAttrInt *)attr)->value; >+ break; >+ >+ case PANGO_ATTR_STRIKETHROUGH: >+ renderer->strikethrough = ((PangoAttrInt *)attr)->value; >+ break; >+ >+ case PANGO_ATTR_FOREGROUND: >+ fg_color = &((PangoAttrColor *)attr)->color; >+ break; >+ >+ case PANGO_ATTR_BACKGROUND: >+ bg_color = &((PangoAttrColor *)attr)->color; >+ break; >+ >+ default: >+ break; >+ } >+ } >+ >+ if (!underline_color) >+ underline_color = fg_color; >+ >+ if (!strikethrough_color) >+ strikethrough_color = fg_color; >+ >+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_FOREGROUND, fg_color); >+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, bg_color); >+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, underline_color); >+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, strikethrough_color); >+} >+ >+/** >+ * pango_renderer_set_matrix: >+ * @renderer: a #PangoRenderer >+ * @matrix: a #PangoMatrix, or %NULL to unset any existing matrix. >+ * (No matrix set is the same as setting the identity matrix.) >+ * >+ * Sets the transformation matrix that will be applied when rendering. >+ * >+ * Since: 1.8 >+ **/ >+void >+pango_renderer_set_matrix (PangoRenderer *renderer, >+ const PangoMatrix *matrix) >+{ >+ g_return_if_fail (PANGO_IS_RENDERER (renderer)); >+ >+ if (renderer->matrix) >+ pango_matrix_free (renderer->matrix); >+ if (matrix) >+ renderer->matrix = pango_matrix_copy (matrix); >+ else >+ renderer->matrix = NULL; >+ >+} >+ >+/** >+ * pango_renderer_get_matrix: >+ * @renderer: a #PangoRenderer >+ * >+ * Gets the transformation matrix that will be applied when >+ * rendering. See pango_renderer_set_matrix(). >+ * >+ * Return value: the matrix, or %NULL if no matrix has been set >+ * (which is the same as the identity matrix). The returned >+ * matrix is owned by Pango and must not be modified or >+ * freed. >+ * >+ * Since: 1.8 >+ **/ >+G_CONST_RETURN PangoMatrix * >+pango_renderer_get_matrix (PangoRenderer *renderer) >+{ >+ g_return_val_if_fail (PANGO_IS_RENDERER (renderer), NULL); >+ >+ return renderer->matrix; >+} >--- mozilla/gfx/src/gtk/nsFontMetricsPango.h.printing 2005-05-02 22:48:30.000000000 +0200 >+++ mozilla/gfx/src/gtk/nsFontMetricsPango.h 2007-07-03 15:40:51.000000000 +0200 >@@ -37,17 +37,53 @@ > * > * ***** END LICENSE BLOCK ***** */ > >+ > #include "nsIFontMetrics.h" > #include "nsIFontEnumerator.h" > #include "nsCRT.h" > #include "nsIAtom.h" > #include "nsString.h" > #include "nsVoidArray.h" >+ >+#ifdef PSPANGO >+#include "nsFontMetricsPS.h" >+#else > #include "nsIFontMetricsGTK.h" >+#endif > > #include <pango/pango.h> > >-class nsFontMetricsPango : public nsIFontMetricsGTK >+#ifdef PSPANGO >+ >+#define CONTEXT_ARG_DEF >+#define CONTEXT_ARG_PASS >+#define CONTEXT_ARG_NULL >+#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextPS *aContext >+#define CONTEXT_AND_SURFACE_ARG_PASS , aContext >+ >+#else >+ >+#define CONTEXT_ARG_DEF , nsRenderingContextGTK *aContext >+#define CONTEXT_ARG_PASS , aContext >+#define CONTEXT_ARG_NULL , NULL >+#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextGTK *aContext, nsDrawingSurfaceGTK *aSurface >+#define CONTEXT_AND_SURFACE_ARG_PASS , aContext, aSurface >+ >+#endif >+ >+ >+#ifdef PSPANGO >+ >+#define nsFontMetricsPango nsFontMetricsPSPango >+#define PSPANGO_PARENT_CLASS nsFontMetricsPS >+ >+#else >+ >+#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK >+ >+#endif >+ >+class nsFontMetricsPango : public PSPANGO_PARENT_CLASS > { > public: > nsFontMetricsPango(); >@@ -134,20 +170,30 @@ public: > { aAveCharWidth = mAveCharWidth; > return NS_OK; }; > >- // nsIFontMetricsGTK (calls from the font rendering layer) >- virtual nsresult GetWidth(const char* aString, PRUint32 aLength, >- nscoord& aWidth, >- nsRenderingContextGTK *aContext); >- virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength, >- nscoord& aWidth, PRInt32 *aFontID, >- nsRenderingContextGTK *aContext); >+ // nsIFontMetrics (calls from the font rendering layer) >+ >+#ifdef PSPANGO >+ NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength); >+ NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength); >+#endif >+ >+ NS_METHOD GetWidth(const char* aString, PRUint32 aLength, >+ nscoord& aWidth >+ CONTEXT_ARG_DEF); >+ NS_METHOD GetWidth(const PRUnichar* aString, PRUint32 aLength, >+ nscoord& aWidth, PRInt32 *aFontID >+ CONTEXT_ARG_DEF); > >- virtual nsresult GetTextDimensions(const PRUnichar* aString, >+ NS_METHOD GetTextDimensions(const char* aString, >+ PRUint32 aLength, >+ nsTextDimensions& aDimensions >+ CONTEXT_ARG_DEF); >+ NS_METHOD GetTextDimensions(const PRUnichar* aString, > PRUint32 aLength, > nsTextDimensions& aDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext); >- virtual nsresult GetTextDimensions(const char* aString, >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF); >+ NS_METHOD GetTextDimensions(const char* aString, > PRInt32 aLength, > PRInt32 aAvailWidth, > PRInt32* aBreaks, >@@ -155,9 +201,9 @@ public: > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, > nsTextDimensions& aLastWordDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext); >- virtual nsresult GetTextDimensions(const PRUnichar* aString, >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF); >+ NS_METHOD GetTextDimensions(const PRUnichar* aString, > PRInt32 aLength, > PRInt32 aAvailWidth, > PRInt32* aBreaks, >@@ -165,37 +211,37 @@ public: > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, > nsTextDimensions& aLastWordDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext); >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF); > >- virtual nsresult DrawString(const char *aString, PRUint32 aLength, >+ NS_METHOD DrawString(const char *aString, PRUint32 aLength, > nscoord aX, nscoord aY, >- const nscoord* aSpacing, >- nsRenderingContextGTK *aContext, >- nsDrawingSurfaceGTK *aSurface); >- virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength, >+ const nscoord* aSpacing >+ CONTEXT_AND_SURFACE_ARG_DEF); >+ NS_METHOD DrawString(const PRUnichar* aString, PRUint32 aLength, > nscoord aX, nscoord aY, > PRInt32 aFontID, >- const nscoord* aSpacing, >- nsRenderingContextGTK *aContext, >- nsDrawingSurfaceGTK *aSurface); >+ const nscoord* aSpacing >+ CONTEXT_AND_SURFACE_ARG_DEF); > > #ifdef MOZ_MATHML >- virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength, >- nsBoundingMetrics &aBoundingMetrics, >- nsRenderingContextGTK *aContext); >- virtual nsresult GetBoundingMetrics(const PRUnichar *aString, >+ NS_METHOD GetBoundingMetrics(const char *aString, PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics >+ CONTEXT_ARG_DEF); >+ NS_METHOD GetBoundingMetrics(const PRUnichar *aString, > PRUint32 aLength, > nsBoundingMetrics &aBoundingMetrics, >- PRInt32 *aFontID, >- nsRenderingContextGTK *aContext); >+ PRInt32 *aFontID >+ CONTEXT_ARG_DEF); > #endif /* MOZ_MATHML */ > >+#ifndef PSPANGO > virtual GdkFont* GetCurrentGDKFont(void); >+#endif > >- virtual nsresult SetRightToLeftText(PRBool aIsRTL); >+ NS_METHOD SetRightToLeftText(PRBool aIsRTL); > >- virtual nsresult GetClusterInfo(const PRUnichar *aText, >+ NS_METHOD GetClusterInfo(const PRUnichar *aText, > PRUint32 aLength, > PRUint8 *aClusterStarts); > >@@ -203,32 +249,35 @@ public: > PRUint32 aLength, > nsPoint aPt); > >- virtual nsresult GetRangeWidth(const PRUnichar *aText, >+ NS_METHOD GetRangeWidth(const PRUnichar *aText, > PRUint32 aLength, > PRUint32 aStart, > PRUint32 aEnd, > PRUint32 &aWidth); > >- virtual nsresult GetRangeWidth(const char *aText, >+ NS_METHOD GetRangeWidth(const char *aText, > PRUint32 aLength, > PRUint32 aStart, > PRUint32 aEnd, > PRUint32 &aWidth); > > // get hints for the font >- static PRUint32 GetHints (void); >+#ifndef PSPANGO >+ static >+#endif >+ PRUint32 GetHints (void); > > // drawing surface methods > static nsresult FamilyExists (nsIDeviceContext *aDevice, > const nsString &aName); > >+ > private: > > // generic font metrics class bits > nsCStringArray mFontList; > nsAutoVoidArray mFontIsGeneric; > >- nsIDeviceContext *mDeviceContext; > nsCOMPtr<nsIAtom> mLangGroup; > nsCString *mGenericFont; > float mPointSize; >@@ -243,6 +292,9 @@ private: > PangoAttrList *mPangoAttrList; > PRBool mIsRTL; > >+#ifndef PSPANGO >+ nsIDeviceContext *mDeviceContext; >+ > // Cached font metrics > nscoord mXHeight; > nscoord mSuperscriptOffset; >@@ -260,8 +312,9 @@ private: > nscoord mMaxDescent; > nscoord mMaxAdvance; > nscoord mSpaceWidth; >- nscoord mPangoSpaceWidth; > nscoord mAveCharWidth; >+#endif >+ nscoord mPangoSpaceWidth; > > // Private methods > nsresult RealizeFont(void); >@@ -270,13 +323,14 @@ private: > static PRBool EnumFontCallback(const nsString &aFamily, > PRBool aIsGeneric, void *aData); > >- void DrawStringSlowly(const gchar *aText, >- const PRUnichar *aOrigString, >- PRUint32 aLength, >- GdkDrawable *aDrawable, >- GdkGC *aGC, gint aX, gint aY, >- PangoLayoutLine *aLine, >- const nscoord *aSpacing); >+ void ApplySpacing(const gchar *aText, >+ PRUint32 aLength, >+ PangoLayoutLine *aLine, >+ const nscoord *aSpacing); >+ void ApplySpacing(const PRUnichar *aText, >+ PRUint32 aLength, >+ PangoLayoutLine *aLine, >+ const nscoord *aSpacing); > > nsresult GetTextDimensionsInternal(const gchar* aString, > PRInt32 aLength, >@@ -285,10 +339,20 @@ private: > PRInt32 aNumBreaks, > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, >- nsTextDimensions& aLastWordDimensions, >- nsRenderingContextGTK *aContext); >+ nsTextDimensions& aLastWordDimensions >+ CONTEXT_ARG_DEF); >+#ifdef MOZ_MATHML >+ void GetBoundingMetricsInternal(PangoLayout *aLayout, >+ nsBoundingMetrics &aBoundingMetrics >+ CONTEXT_ARG_DEF); >+#endif /* MOZ_MATHML */ >+ >+ void FixupSpaceWidths (PangoLayout *aLayout); > >- void FixupSpaceWidths (PangoLayout *aLayout, const char *aString); >+ PangoLayout* GetLayout (const PRUnichar* aText, >+ PRUint32 aLength); >+ PangoLayout* GetLayout (const gchar* aText, >+ PRInt32 aLength); > }; > > class nsFontEnumeratorPango : public nsIFontEnumerator >--- mozilla/gfx/src/gtk/nsFontMetricsPango.cpp.printing 2007-07-03 15:40:51.000000000 +0200 >+++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -21,6 +21,8 @@ > * are Copyright (C) 2004 the Initial Developer. All Rights Reserved. > * > * Contributor(s): >+ * Christopher Blizzard <blizzard@mozilla.org> >+ * Behdad Esfahbod <behdad@behdad.org> > * > * Alternatively, the contents of this file may be used under the terms of > * either the GNU General Public License Version 2 or later (the "GPL"), or >@@ -36,6 +38,10 @@ > * > * ***** END LICENSE BLOCK ***** */ > >+#define PANGO_ENABLE_BACKEND >+ >+#include "nsFontMetricsPango.h" >+ > #include <strings.h> > #include "nsFont.h" > #include "nsIDeviceContext.h" >@@ -43,27 +49,41 @@ > #include "nsIPref.h" > #include "nsServiceManagerUtils.h" > >-#define PANGO_ENABLE_BACKEND >-#define PANGO_ENABLE_ENGINE >- >-#include "nsFontMetricsPango.h" >-#include "nsRenderingContextGTK.h" >-#include "nsDeviceContextGTK.h" > #include "nsFontConfigUtils.h" > > #include "nsUnicharUtils.h" > #include "nsQuickSort.h" > #include "nsFontConfigUtils.h" >+#include "mozilla-decoder.h" >+ >+#define FORCE_PR_LOG >+#include "prlog.h" >+ > > #include <fontconfig/fontconfig.h> >-#include <gdk/gdk.h> >-#include <gdk/gdkx.h> > #include <freetype/tttables.h> > >-#include "mozilla-decoder.h" >+#include <pango/pango.h> >+#include <pango/pangofc-font.h> > >-#define FORCE_PR_LOG >-#include "prlog.h" >+#ifdef PSPANGO >+#include <pango/pangoft2.h> >+#include "pango-renderer.h" >+#include "nsRenderingContextPS.h" >+#include "nsDeviceContextPS.h" >+#include "nsType1.h" >+#else >+#include <gdk/gdk.h> >+#include <gdk/gdkx.h> >+#include "nsRenderingContextGTK.h" >+#include "nsDeviceContextGTK.h" >+#endif >+ >+#ifdef MOZ_ENABLE_PANGO >+#ifndef PANGO_GLYPH_EMPTY >+#define PANGO_GLYPH_EMPTY 0 >+#endif >+#endif > > // Globals > >@@ -108,6 +128,49 @@ static nsresult EnumFontsPango (nsI > PRUint32* aCount, PRUnichar*** aResult); > static int CompareFontNames (const void* aArg1, const void* aArg2, > void* aClosure); >+static void utf16_to_utf8 (const PRUnichar* aString, PRUint32 aLength, >+ char *&text, gint &text_len); >+ >+#ifdef PSPANGO >+static void >+default_substitute (FcPattern *pattern, >+ gpointer data) >+{ >+ FcPatternDel (pattern, FC_HINTING); >+ FcPatternAddBool (pattern, FC_HINTING, 0); >+} >+#endif >+ >+static PangoFontMap * >+get_fontmap (void) >+{ >+ static PangoFontMap *fontmap = NULL; >+ >+ if (!fontmap) { >+#ifdef PSPANGO >+ fontmap = pango_ft2_font_map_new (); >+ pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.); >+ pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL); >+#else >+ PangoContext* context = gdk_pango_context_get (); >+ fontmap = pango_context_get_font_map (context); >+ g_object_unref (context); >+#endif >+ } >+ >+ return fontmap; >+} >+ >+static PangoContext * >+get_context (void) >+{ >+#ifdef PSPANGO >+ return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ()); >+#else >+ return gdk_pango_context_get(); >+#endif >+} >+ > > nsFontMetricsPango::nsFontMetricsPango() > { >@@ -129,7 +192,7 @@ nsFontMetricsPango::nsFontMetricsPango() > return; > > // Initialized the custom decoders >- if (!mozilla_decoders_init()) >+ if (!mozilla_decoders_init(get_fontmap ())) > initialized = PR_TRUE; > } > >@@ -169,14 +232,20 @@ nsFontMetricsPango::Init(const nsFont& a > mLangGroup = aLangGroup; > > // Hang on to the device context >+#ifdef PSPANGO >+ mDeviceContext = (nsDeviceContextPS *)aContext; >+#else > mDeviceContext = aContext; >+#endif > > mPointSize = NSTwipsToFloatPoints(mFont.size); > >+#ifndef PSPANGO > // Make sure to clamp the pixel size to something reasonable so we > // don't make the X server blow up. > nscoord screenPixels = gdk_screen_height(); > mPointSize = PR_MIN(screenPixels * FONT_MAX_FONT_SCALE, mPointSize); >+#endif > > // enumerate over the font names passed in > mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this); >@@ -325,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi > > // mPangoSpaceWidth > PangoLayout *layout = pango_layout_new(mPangoContext); >- pango_layout_set_text(layout, " ", 1); >+ pango_layout_set_text(layout, " ", -1); > int pswidth, psheight; > pango_layout_get_size(layout, &pswidth, &psheight); > mPangoSpaceWidth = pswidth; >@@ -333,14 +402,14 @@ nsFontMetricsPango::CacheFontMetrics(voi > > // mSpaceWidth (width of a space) > nscoord tmpWidth; >- GetWidth(" ", 1, tmpWidth, NULL); >+ GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL); > mSpaceWidth = tmpWidth; > > // mAveCharWidth (width of an 'average' char) > // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents); > //rawWidth = extents.width; > //mAveCharWidth = NSToCoordRound(rawWidth * f); >- GetWidth("x", 1, tmpWidth, NULL); >+ GetWidth("x", 1, tmpWidth CONTEXT_ARG_NULL); > mAveCharWidth = tmpWidth; > > // mXHeight (height of an 'x' character) >@@ -456,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont > > // nsIFontMetricsPango impl > >-nsresult >-nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength, >- nscoord& aWidth, >- nsRenderingContextGTK *aContext) >+#ifdef PSPANGO >+NS_IMETHODIMP >+nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength) > { >- PangoLayout *layout = pango_layout_new(mPangoContext); >- >- pango_layout_set_text(layout, aString, aLength); >+ return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL); >+} > >- if (mPangoSpaceWidth) >- FixupSpaceWidths(layout, aString); >+NS_IMETHODIMP >+nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength) >+{ >+ return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL); >+} >+#endif > >+nsresult >+nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength, >+ nscoord& aWidth >+ CONTEXT_ARG_DEF) >+{ > int width, height; >- >+ PangoLayout *layout = GetLayout(aString, aLength); > pango_layout_get_size(layout, &width, &height); >- > g_object_unref(layout); > >- float f; >- f = mDeviceContext->DevUnitsToAppUnits(); >+ float f = mDeviceContext->DevUnitsToAppUnits(); > aWidth = NSToCoordRound(width * f / PANGO_SCALE); > >- // printf("GetWidth (char *) %d\n", aWidth); >- > return NS_OK; > } > > nsresult > nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength, >- nscoord& aWidth, PRInt32 *aFontID, >- nsRenderingContextGTK *aContext) >+ nscoord& aWidth, PRInt32 *aFontID >+ CONTEXT_ARG_DEF) > { >- nsresult rv = NS_OK; >- PangoLayout *layout = pango_layout_new(mPangoContext); >- >- gchar *text = g_utf16_to_utf8(aString, aLength, >- NULL, NULL, NULL); >- >- if (!text) { >- aWidth = 0; >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); >- DUMP_PRUNICHAR(aString, aLength) >-#endif >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >- > gint width, height; >- >- pango_layout_set_text(layout, text, strlen(text)); >- FixupSpaceWidths(layout, text); >+ PangoLayout *layout = GetLayout(aString, aLength); > pango_layout_get_size(layout, &width, &height); >+ g_object_unref(layout); > >- float f; >- f = mDeviceContext->DevUnitsToAppUnits(); >+ float f = mDeviceContext->DevUnitsToAppUnits(); > aWidth = NSToCoordRound(width * f / PANGO_SCALE); > >- // printf("GetWidth %d\n", aWidth); >- >- loser: >- g_free(text); >- g_object_unref(layout); >- >- return rv; >+ return NS_OK; > } > > > nsresult >-nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString, >+nsFontMetricsPango::GetTextDimensions(const char* aString, > PRUint32 aLength, >- nsTextDimensions& aDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext) >+ nsTextDimensions& aDimensions >+ CONTEXT_ARG_DEF) > { >- nsresult rv = NS_OK; >- >- PangoLayout *layout = pango_layout_new(mPangoContext); >- >- gchar *text = g_utf16_to_utf8(aString, aLength, >- NULL, NULL, NULL); >+ PangoLayout *layout = GetLayout(aString, aLength); >+ PangoLayoutLine *line = pango_layout_get_line(layout, 0); > >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow"); >- DUMP_PRUNICHAR(aString, aLength) >-#endif >- aDimensions.width = 0; >- aDimensions.ascent = 0; >- aDimensions.descent = 0; >- >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >- >+ PangoRectangle logical; >+ pango_layout_line_get_extents(line, NULL, &logical); >+ g_object_unref(layout); > >- pango_layout_set_text(layout, text, strlen(text)); >- FixupSpaceWidths(layout, text); >+ float P2T = mDeviceContext->DevUnitsToAppUnits(); > >- // Get the logical extents >- PangoLayoutLine *line; >- if (pango_layout_get_line_count(layout) != 1) { >- printf("Warning: more than one line!\n"); >- } >- line = pango_layout_get_line(layout, 0); >+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE); >+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE); >+ aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE); > >- PangoRectangle rect; >- pango_layout_line_get_extents(line, NULL, &rect); >+ return NS_OK; >+} > >- float P2T; >- P2T = mDeviceContext->DevUnitsToAppUnits(); >+nsresult >+nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString, >+ PRUint32 aLength, >+ nsTextDimensions& aDimensions, >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF) >+{ >+ PangoLayout *layout = GetLayout(aString, aLength); >+ PangoLayoutLine *line = pango_layout_get_line(layout, 0); > >- aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE); >- aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE); >- aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE); >+ PangoRectangle logical; >+ pango_layout_line_get_extents(line, NULL, &logical); >+ g_object_unref(layout); > >- // printf("GetTextDimensions %d %d %d\n", aDimensions.width, >- //aDimensions.ascent, aDimensions.descent); >+ float P2T = mDeviceContext->DevUnitsToAppUnits(); > >- loser: >- g_free(text); >- g_object_unref(layout); >+ aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE); >+ aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE); >+ aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE); > >- return rv; >+ return NS_OK; > } > > nsresult >@@ -591,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, > nsTextDimensions& aLastWordDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext) >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF) > { > > return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, > aNumBreaks, aDimensions, aNumCharsFit, >- aLastWordDimensions, aContext); >+ aLastWordDimensions CONTEXT_ARG_PASS); > > } > >@@ -610,8 +645,8 @@ nsFontMetricsPango::GetTextDimensions(co > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, > nsTextDimensions& aLastWordDimensions, >- PRInt32* aFontID, >- nsRenderingContextGTK *aContext) >+ PRInt32* aFontID >+ CONTEXT_ARG_DEF) > { > nsresult rv = NS_OK; > PRInt32 curBreak = 0; >@@ -619,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co > > PRInt32 *utf8Breaks = new PRInt32[aNumBreaks]; > >- gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength, >- NULL, NULL, NULL); >+ gchar* text; >+ gint text_len; >+ utf16_to_utf8 (aString, aLength, text, text_len); > > curChar = text; > >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); >- DUMP_PRUNICHAR(aString, (PRUint32)aLength) >-#endif >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >- > // Covert the utf16 break offsets to utf8 break offsets > for (PRInt32 curOffset=0; curOffset < aLength; >- curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { >+ curOffset++, curChar = g_utf8_next_char(curChar)) { > if (aBreaks[curBreak] == curOffset) { > utf8Breaks[curBreak] = curChar - text; > curBreak++; >@@ -649,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co > utf8Breaks[curBreak] = curChar - text; > > #if 0 >- if (strlen(text) != aLength) { >- printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text)); >+ if (text_len != aLength) { >+ printf("Different lengths for utf16 %d and utf8 %d\n", aLength, text_len); > DUMP_PRUNICHAR(aString, aLength) >- DUMP_PRUNICHAR(text, strlen(text)) >+ DUMP_PRUNICHAR(text, text_len) > for (PRInt32 i = 0; i < aNumBreaks; ++i) { > printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]); > } >@@ -662,9 +689,9 @@ nsFontMetricsPango::GetTextDimensions(co > // We'll use curBreak to indicate which of the breaks end up being > // used for the break point for this line. > curBreak = 0; >- rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks, >+ rv = GetTextDimensionsInternal(text, text_len, aAvailWidth, utf8Breaks, > aNumBreaks, aDimensions, aNumCharsFit, >- aLastWordDimensions, aContext); >+ aLastWordDimensions CONTEXT_ARG_PASS); > > // Figure out which of the breaks we ended up using to convert > // back to utf16 - start from the end. >@@ -677,204 +704,366 @@ nsFontMetricsPango::GetTextDimensions(co > } > } > >- loser: >- if (text) >- g_free(text); >+ g_free(text); > > delete[] utf8Breaks; > > return rv; > } > >-nsresult >-nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength, >- nscoord aX, nscoord aY, >- const nscoord* aSpacing, >- nsRenderingContextGTK *aContext, >- nsDrawingSurfaceGTK *aSurface) >+#ifdef PSPANGO >+ >+typedef struct _nsPSPangoRenderer nsPSPangoRenderer; >+typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass; >+ >+struct _nsPSPangoRenderer > { >- PangoLayout *layout = pango_layout_new(mPangoContext); >+ PangoRenderer parent_instance; >+ nsRenderingContextPS *psContext; >+ nsFontMetricsPSPango *psPangoFontMetrics; >+ float zoom; >+}; > >- pango_layout_set_text(layout, aString, aLength); >- FixupSpaceWidths(layout, aString); >+struct _nsPSPangoRendererClass >+{ >+ PangoRendererClass parent_class; >+}; > >- int x = aX; >- int y = aY; >+#define _PS_TYPE_PANGO_RENDERER (_ps_pango_renderer_get_type()) >+#define _PS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer)) >+#define _PS_IS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER)) >+#define _PS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass)) >+#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER)) >+#define _PS_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass)) > >- aContext->GetTranMatrix()->TransformCoord(&x, &y); >+G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER) > >- PangoLayoutLine *line; >- if (pango_layout_get_line_count(layout) != 1) { >- printf("Warning: more than one line!\n"); >- } >- line = pango_layout_get_line(layout, 0); >+static PangoRenderer * >+get_renderer (void) >+{ >+ static PangoRenderer *renderer = NULL; > >- aContext->UpdateGC(); >- GdkGC *gc = aContext->GetGC(); >+ if (!renderer) >+ renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL); > >- if (aSpacing && *aSpacing) { >- DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(), >- gc, x, y, line, aSpacing); >- } >- else { >- gdk_draw_layout_line(aSurface->GetDrawable(), gc, >- x, y, >- line); >- } >+ return renderer; >+} > >- g_object_unref(gc); >- g_object_unref(layout); >+static void >+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y); > >- // printf("DrawString (char *)\n"); >+static void >+_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass) >+{ >+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); >+ >+ renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs; >+} > >- return NS_OK; >+static void >+_ps_pango_renderer_init (nsPSPangoRenderer *renderer) >+{ >+} >+ >+class nsPangoType1Generator : public nsPSFontGenerator { >+public: >+ nsPangoType1Generator(); >+ ~nsPangoType1Generator(); >+ nsresult Init(PangoFont *aFont); >+ void GeneratePSFont(FILE* aFile); >+ >+protected: >+ PangoFont *mFont; >+}; >+ >+nsPangoType1Generator::nsPangoType1Generator() >+{ > } > > nsresult >-nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength, >- nscoord aX, nscoord aY, >- PRInt32 aFontID, >- const nscoord* aSpacing, >- nsRenderingContextGTK *aContext, >- nsDrawingSurfaceGTK *aSurface) >+nsPangoType1Generator::Init(PangoFont *aFont) > { >- nsresult rv = NS_OK; >- int x = aX; >- int y = aY; >+ NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE); >+ mFont = aFont; >+ g_object_ref (mFont); >+ return NS_OK; >+} > >- aContext->UpdateGC(); >- GdkGC *gc = aContext->GetGC(); >+nsPangoType1Generator::~nsPangoType1Generator() >+{ >+ g_object_unref (mFont); >+ mFont = nsnull; >+} > >- PangoLayout *layout = pango_layout_new(mPangoContext); >+void nsPangoType1Generator::GeneratePSFont(FILE* aFile) >+{ >+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont); > >- gchar *text = g_utf16_to_utf8(aString, aLength, >- NULL, NULL, NULL); >+ if (face == nsnull) >+ return; > >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow"); >- DUMP_PRUNICHAR(aString, aLength) >-#endif >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >+ int wmode = 0; >+ if (mGlyphSubset->Count()) >+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); > >- pango_layout_set_text(layout, text, strlen(text)); >- FixupSpaceWidths(layout, text); >+ pango_fc_font_unlock_face ((PangoFcFont *) mFont); >+} > >- aContext->GetTranMatrix()->TransformCoord(&x, &y); >+typedef struct >+{ >+ nsCString *FontNameBase; >+ nsCStringKey *key; >+ int font_size; >+} PSPangoFontData; > >- PangoLayoutLine *line; >- if (pango_layout_get_line_count(layout) != 1) { >- printf("Warning: more than one line!\n"); >- } >- line = pango_layout_get_line(layout, 0); >+static void >+ps_pango_font_data_destroy (PSPangoFontData *data) >+{ >+ delete data->key; >+ delete data->FontNameBase; >+ g_free (data); >+} > >- if (aSpacing && *aSpacing) { >- DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(), >- gc, x, y, line, aSpacing); >- } >- else { >- gdk_draw_layout_line(aSurface->GetDrawable(), gc, >- x, y, >- line); >+static void >+_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer, >+ PangoFont *font, >+ PangoGlyphString *glyphs, >+ int x, >+ int y) >+{ >+ if (!glyphs->num_glyphs) >+ return; >+ >+ static GQuark data_quark = 0; >+ if (!data_quark) >+ data_quark = g_quark_from_static_string ("ps-pango-font-data"); >+ >+ PSPangoFontData *data; >+ if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark))) >+ { >+ data = g_new (PSPangoFontData, 1); >+ >+ FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font); >+ if (face == nsnull) >+ return; >+ int wmode = 0; >+ data->FontNameBase = new nsCString (); >+ if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) { >+ g_free (data); >+ pango_fc_font_unlock_face ((PangoFcFont *) font); >+ return; >+ } >+ pango_fc_font_unlock_face ((PangoFcFont *) font); >+ >+ PangoFontDescription *desc = pango_font_describe (font); >+ data->font_size = pango_font_description_get_size (desc); >+ pango_font_description_free (desc); >+ >+ data->key = new nsCStringKey (*data->FontNameBase); >+ >+ g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy); >+ } >+ >+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer; >+ nsRenderingContextPS *aContext = ps_renderer->psContext; >+ nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics; >+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext()); >+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); >+ nsHashtable *psFGList = dc->GetPSFontGeneratorList(); >+ g_return_if_fail (psFGList); >+ nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key); >+ if (!psFontGen) { >+ nsresult rv; >+ psFontGen = new nsPangoType1Generator; >+ g_return_if_fail (psFontGen); >+ rv = ((nsPangoType1Generator*)psFontGen)->Init(font); >+ if (NS_FAILED(rv)) { >+ delete psFontGen; >+ return; >+ } >+ psFGList->Put(data->key, (void *) psFontGen); >+ } >+ nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE); >+ >+ g_return_if_fail (aContext); >+ g_return_if_fail (psObj); >+ >+ nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE); >+ nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE); >+ psObj->moveto(aX, aY); >+ >+ PRInt32 currSubFont, prevSubFont = -1; >+ PRUint32 i; >+ PangoGlyphString gl; >+ >+ gl.glyphs = glyphs->glyphs; >+ gl.num_glyphs = 0; >+ currSubFont = prevSubFont; >+ for (i = 0; i < glyphs->num_glyphs; ++i) { >+ PangoGlyph glyph = glyphs->glyphs[i].glyph; >+ >+ if (glyph != PANGO_GLYPH_EMPTY) >+ currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph); >+ >+ if (prevSubFont != currSubFont) { >+ if (prevSubFont != -1) >+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont); >+ >+ psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont); >+ prevSubFont = currSubFont; >+ gl.glyphs = glyphs->glyphs + i; >+ gl.num_glyphs = 0; > } > >- loser: >+ gl.num_glyphs++; >+ } > >- g_free(text); >- g_object_unref(gc); >- g_object_unref(layout); >+ if (prevSubFont != -1) >+ psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont); >+} > >- // printf("DrawString\n"); >+#endif > >- return rv; >+static void >+draw_layout_line (int x, int y, >+ PangoLayoutLine *line, >+ nsFontMetricsPango *fm >+ CONTEXT_AND_SURFACE_ARG_DEF) >+{ >+#ifdef PSPANGO >+ PangoRenderer *renderer = get_renderer (); >+ nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer; >+ ps_renderer->psContext = aContext; >+ ps_renderer->psPangoFontMetrics = fm; >+ nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, fm->GetDeviceContext()); >+ ps_renderer->zoom = dc->DevUnitsToAppUnits(); >+ >+ pango_renderer_draw_layout_line (renderer, line, >+ NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom), >+ NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom)); >+#else >+ aContext->UpdateGC(); >+ GdkGC *gc = aContext->GetGC(); >+ gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line); >+ g_object_unref(gc); >+#endif > } > >-#ifdef MOZ_MATHML >+ > nsresult >-nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength, >- nsBoundingMetrics &aBoundingMetrics, >- nsRenderingContextGTK *aContext) >+nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ const nscoord* aSpacing >+ CONTEXT_AND_SURFACE_ARG_DEF) > { >- printf("GetBoundingMetrics (char *)\n"); >- return NS_ERROR_FAILURE; >+ int x = aX; >+ int y = aY; >+ >+ aContext->GetTranMatrix()->TransformCoord(&x, &y); >+ >+ PangoLayout *layout = GetLayout(aString, aLength); >+ PangoLayoutLine *line = pango_layout_get_line(layout, 0); >+ >+ ApplySpacing(aString, aLength, line, aSpacing); >+ draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS); >+ >+ g_object_unref(layout); >+ >+ return NS_OK; > } > > nsresult >-nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString, >- PRUint32 aLength, >- nsBoundingMetrics &aBoundingMetrics, >- PRInt32 *aFontID, >- nsRenderingContextGTK *aContext) >+nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ PRInt32 aFontID, >+ const nscoord* aSpacing >+ CONTEXT_AND_SURFACE_ARG_DEF) > { >- nsresult rv = NS_OK; >- PangoLayout *layout = pango_layout_new(mPangoContext); >+ int x = aX; >+ int y = aY; > >- gchar *text = g_utf16_to_utf8(aString, aLength, >- NULL, NULL, NULL); >+ aContext->GetTranMatrix()->TransformCoord(&x, &y); > >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow"); >- DUMP_PRUNICHAR(aString, aLength) >-#endif >- aBoundingMetrics.leftBearing = 0; >- aBoundingMetrics.rightBearing = 0; >- aBoundingMetrics.width = 0; >- aBoundingMetrics.ascent = 0; >- aBoundingMetrics.descent = 0; >+ PangoLayout *layout = GetLayout(aString, aLength); >+ PangoLayoutLine *line = pango_layout_get_line(layout, 0); > >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >+ ApplySpacing(aString, aLength, line, aSpacing); >+ draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS); > >- pango_layout_set_text(layout, text, -1); >- FixupSpaceWidths(layout, text); >+ g_object_unref(layout); > >- PangoLayoutLine *line; >- if (pango_layout_get_line_count(layout) != 1) { >- printf("Warning: more than one line!\n"); >- } >- line = pango_layout_get_line(layout, 0); >+ return NS_OK; >+} >+ >+#ifdef MOZ_MATHML >+void >+nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout, >+ nsBoundingMetrics &aBoundingMetrics >+ CONTEXT_ARG_DEF) >+{ >+ PangoLayoutLine *line = pango_layout_get_line(aLayout, 0); > > // Get the ink and logical extents > PangoRectangle ink, logical; > pango_layout_line_get_extents(line, &ink, &logical); > >- float P2T; >- P2T = mDeviceContext->DevUnitsToAppUnits(); >+ float P2T = mDeviceContext->DevUnitsToAppUnits(); > > aBoundingMetrics.leftBearing = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE); > aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE); > aBoundingMetrics.ascent = NSToCoordRound(PANGO_ASCENT(ink) * P2T / PANGO_SCALE); > aBoundingMetrics.descent = NSToCoordRound(PANGO_DESCENT(ink) * P2T / PANGO_SCALE); > aBoundingMetrics.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE); >+} > >- loser: >- g_free(text); >+ >+nsresult >+nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics >+ CONTEXT_ARG_DEF) >+{ >+ PangoLayout *layout = GetLayout(aString, aLength); >+ GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS); > g_object_unref(layout); > >- return rv; >+ return NS_OK; >+} >+ >+nsresult >+nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString, >+ PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics, >+ PRInt32 *aFontID >+ CONTEXT_ARG_DEF) >+{ >+ PangoLayout *layout = GetLayout(aString, aLength); >+ GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS); >+ g_object_unref(layout); >+ >+ return NS_OK; > } > > #endif /* MOZ_MATHML */ > >+#ifndef PSPANGO > GdkFont* > nsFontMetricsPango::GetCurrentGDKFont(void) > { > return nsnull; > } >+#endif > > nsresult > nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL) > { > if (aIsRTL) { > if (!mRTLPangoContext) { >- mRTLPangoContext = gdk_pango_context_get(); >+ mRTLPangoContext = get_context(); > pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL); >- >- gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap()); > pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup)); > pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc); > } >@@ -893,34 +1082,18 @@ nsFontMetricsPango::GetClusterInfo(const > PRUint32 aLength, > PRUint8 *aClusterStarts) > { >- nsresult rv = NS_OK; > PangoLogAttr *attrs = NULL; > gint n_attrs = 0; >- PangoLayout *layout = pango_layout_new(mPangoContext); >- >- // Convert the incoming UTF-16 to UTF-8 >- gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); >- >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); >- DUMP_PRUNICHAR(aText, aLength) >-#endif >- rv = NS_ERROR_FAILURE; >- goto loser; >- } > >- // Set up the pango layout >- pango_layout_set_text(layout, text, strlen(text)); >- FixupSpaceWidths(layout, text); >+ PangoLayout *layout = GetLayout(aText, aLength); >+ pango_layout_get_log_attrs(layout, &attrs, &n_attrs); >+ g_object_unref(layout); > > // Convert back to UTF-16 while filling in the cluster info > // structure. >- pango_layout_get_log_attrs(layout, &attrs, &n_attrs); >- > for (PRUint32 pos = 0; pos < aLength; pos++) { > if (IS_HIGH_SURROGATE(aText[pos])) { >- aClusterStarts[pos] = 1; >+ aClusterStarts[pos] = 1;//FIXME: shouldn't this be zero?! --be > pos++; > } > else { >@@ -928,56 +1101,34 @@ nsFontMetricsPango::GetClusterInfo(const > } > } > >- loser: >- if (attrs) >- g_free(attrs); >- if (text) >- g_free(text); >- if (layout) >- g_object_unref(layout); >+ g_free(attrs); > >- return rv; >+ return NS_OK; > } > > PRInt32 >-nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, >- nsPoint aPt) >+nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt) > { > int trailing = 0; > int inx = 0; >- const gchar *curChar; > PRInt32 retval = 0; > > float f = mDeviceContext->AppUnitsToDevUnits(); > >- PangoLayout *layout = pango_layout_new(mPangoContext); > PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f); > PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f); > >- // Convert the incoming UTF-16 to UTF-8 >- gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); >- >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); >- DUMP_PRUNICHAR(aText, aLength) >-#endif >- retval = -1; >- goto loser; >- } >- >- // Set up the pango layout >- pango_layout_set_text(layout, text, strlen(text)); >- FixupSpaceWidths(layout, text); >+ PangoLayout *layout = GetLayout(aText, aLength); > > pango_layout_xy_to_index(layout, localX, localY, > &inx, &trailing); > > // Convert the index back to the utf-16 index >- curChar = text; >+ const gchar *text = pango_layout_get_text (layout); >+ const gchar *curChar = text; > > for (PRUint32 curOffset=0; curOffset < aLength; >- curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { >+ curOffset++, curChar = g_utf8_next_char(curChar)) { > > // Check for a match before checking for a surrogate pair > if (curChar - text == inx) { >@@ -1000,13 +1151,9 @@ nsFontMetricsPango::GetPosition(const PR > trailing--; > } > >- loser: >- if (text) >- g_free(text); >- if (layout) >- g_object_unref(layout); >+ g_object_unref(layout); > >- return retval; >+ return retval; > } > > nsresult >@@ -1016,28 +1163,21 @@ nsFontMetricsPango::GetRangeWidth(const > PRUint32 aEnd, > PRUint32 &aWidth) > { >- nsresult rv = NS_OK; > PRUint32 utf8Start = 0; > PRUint32 utf8End = 0; > > aWidth = 0; > > // Convert the incoming UTF-16 to UTF-8 >- gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); >- gchar *curChar = text; > >- if (!text) { >-#ifdef DEBUG >- NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); >- DUMP_PRUNICHAR(aText, aLength) >-#endif >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >+ gchar* text; >+ gint text_len; >+ utf16_to_utf8 (aText, aLength, text, text_len); >+ gchar *curChar = text; > > // Convert the utf16 offsets into utf8 offsets > for (PRUint32 curOffset = 0; curOffset < aLength; >- curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { >+ curOffset++, curChar = g_utf8_next_char(curChar)) { > > if (curOffset == aStart) > utf8Start = curChar - text; >@@ -1051,15 +1191,13 @@ nsFontMetricsPango::GetRangeWidth(const > > // Special case where the end index is the same as the length > if (aLength == aEnd) >- utf8End = strlen(text); >+ utf8End = text_len; > >- rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth); >+ GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth); > >- loser: >- if (text) >- g_free(text); >+ g_free(text); > >- return rv; >+ return NS_OK; > } > > nsresult >@@ -1069,43 +1207,26 @@ nsFontMetricsPango::GetRangeWidth(const > PRUint32 aEnd, > PRUint32 &aWidth) > { >- nsresult rv = NS_OK; > int *ranges = NULL; > int n_ranges = 0; > float f; > > aWidth = 0; > >- PangoLayout *layout = pango_layout_new(mPangoContext); >- >- if (!aText) { >- rv = NS_ERROR_FAILURE; >- goto loser; >- } >- >- pango_layout_set_text(layout, aText, aLength); >- FixupSpaceWidths(layout, aText); >- >- PangoLayoutLine *line; >- if (pango_layout_get_line_count(layout) != 1) { >- printf("Warning: more than one line!\n"); >- } >- line = pango_layout_get_line(layout, 0); >+ PangoLayout *layout = GetLayout(aText, aLength); >+ PangoLayoutLine *line = pango_layout_get_line(layout, 0); > > pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges); > > aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]); > > f = mDeviceContext-> DevUnitsToAppUnits(); >- aWidth = nscoord(aWidth * f / PANGO_SCALE); >+ aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE); > >- loser: >- if (ranges) >- g_free(ranges); >- if (layout) >- g_object_unref(layout); >+ g_free(ranges); >+ g_object_unref(layout); > >- return rv; >+ return NS_OK; > } > > /* static */ >@@ -1128,7 +1249,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi > NS_ConvertUTF16toUTF8 name(aName); > > nsresult rv = NS_ERROR_FAILURE; >- PangoContext *context = gdk_pango_context_get(); >+ PangoContext *context = get_context(); > PangoFontFamily **familyList; > int n; > >@@ -1227,16 +1348,13 @@ nsFontMetricsPango::RealizeFont(void) > > // Now that we have the font description set up, create the > // context. >- mLTRPangoContext = gdk_pango_context_get(); >+ mLTRPangoContext = get_context(); > mPangoContext = mLTRPangoContext; > > // Make sure to set the base direction to LTR - if layout needs to > // render RTL text it will use ::SetRightToLeftText() > pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR); > >- // Set the color map so we can draw later. >- gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap()); >- > // Set the pango language now that we have a context > pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup)); > >@@ -1274,79 +1392,268 @@ nsFontMetricsPango::EnumFontCallback(con > * This is only used when there's per-character spacing happening. > * Well, really it can be either line or character spacing but it's > * just turtles all the way down! >+ * >+ * To do it correctly (ligatures, etc) we need machinery that is private >+ * in Pango. IMPORT IT: >+ */ >+ >+#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter >+#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter >+ >+#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0) >+ >+/* Structure holding state when we're iterating over a GlyphItem. >+ * start_index/cluster_end (and range_start/range_end in >+ * apply_attrs()) are offsets into the text, so note the difference >+ * of glyph_item->item->offset between them and clusters in the >+ * log_clusters[] array. > */ >+typedef struct _PangoGlyphItemIter PangoGlyphItemIter; >+ >+struct _PangoGlyphItemIter >+{ >+ PangoGlyphItem *glyph_item; >+ const gchar *text; >+ >+ int start_glyph; >+ int start_index; >+ int start_char; >+ >+ int end_glyph; >+ int end_index; >+ int end_char; >+}; >+ >+/** >+ * _pango_glyph_item_iter_next_cluster: >+ * @iter: a #PangoGlyphItemIter >+ * >+ * Advances the iterator to the next cluster in the glyph item. >+ * >+ * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the >+ * last cluster. >+ **/ >+static gboolean >+_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter) >+{ >+ int glyph_index = iter->end_glyph; >+ PangoGlyphString *glyphs = iter->glyph_item->glyphs; >+ PangoItem *item = iter->glyph_item->item; >+ >+ if (LTR (iter->glyph_item)) >+ { >+ if (glyph_index == glyphs->num_glyphs) >+ return FALSE; >+ } >+ else >+ { >+ if (glyph_index < 0) >+ return FALSE; >+ } >+ >+ iter->start_glyph = iter->end_glyph; >+ iter->start_index = iter->end_index; >+ iter->start_char = iter->end_char; >+ >+ if (LTR (iter->glyph_item)) >+ { >+ while (TRUE) >+ { >+ glyph_index++; >+ >+ if (glyph_index == glyphs->num_glyphs) >+ { >+ iter->end_index = item->offset + item->length; >+ iter->end_char = item->num_chars; >+ break; >+ } >+ >+ if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index) >+ { >+ iter->end_index = item->offset + glyphs->log_clusters[glyph_index]; >+ iter->end_char += g_utf8_strlen (iter->text + iter->start_index, >+ iter->end_index - iter->start_index); >+ break; >+ } >+ } >+ } >+ else /* RTL */ >+ { >+ while (TRUE) >+ { >+ glyph_index--; >+ >+ if (glyph_index < 0) >+ { >+ iter->end_index = item->offset + item->length; >+ iter->end_char = item->num_chars; >+ break; >+ } >+ >+ if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index) >+ { >+ iter->end_index = item->offset + glyphs->log_clusters[glyph_index]; >+ iter->end_char += g_utf8_strlen (iter->text + iter->start_index, >+ iter->end_index - iter->start_index); >+ break; >+ } >+ } >+ } >+ >+ iter->end_glyph = glyph_index; >+ return TRUE; >+} >+ >+/** >+ * _pango_glyph_item_iter_init_start: >+ * @iter: pointer to a #PangoGlyphItemIter structure >+ * @glyph_item: the glyph item that the iter points into >+ * @text: text corresponding to the glyph item >+ * >+ * Initializes a #PangoGlyphItemIter structure to point to the >+ * first cluster in a glyph item. >+ * >+ * Return value: %FALSE if there are no clusters in the glyph item; >+ * in this case, the state of the iter is undefined. >+ **/ >+static gboolean >+_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter, >+ PangoGlyphItem *glyph_item, >+ const char *text) >+{ >+ iter->glyph_item = glyph_item; >+ iter->text = text; >+ >+ if (LTR (glyph_item)) >+ iter->end_glyph = 0; >+ else >+ iter->end_glyph = glyph_item->glyphs->num_glyphs - 1; >+ >+ iter->end_index = glyph_item->item->offset; >+ iter->end_char = 0; >+ >+ /* Advance onto the first cluster of the glyph item */ >+ return _pango_glyph_item_iter_next_cluster (iter); >+} >+ > > void >-nsFontMetricsPango::DrawStringSlowly(const gchar *aText, >- const PRUnichar *aOrigString, >- PRUint32 aLength, >- GdkDrawable *aDrawable, >- GdkGC *aGC, gint aX, gint aY, >- PangoLayoutLine *aLine, >- const nscoord *aSpacing) >-{ >- float app2dev; >- app2dev = mDeviceContext->AppUnitsToDevUnits(); >- gint offset = 0; >+nsFontMetricsPango::ApplySpacing(const gchar *aText, >+ PRUint32 aLength, >+ PangoLayoutLine *aLine, >+ const nscoord *aSpacing) >+{ >+ if (!(aSpacing && *aSpacing)) >+ return; >+ >+ float app2dev = mDeviceContext->AppUnitsToDevUnits(); > > /* > * We walk the list of glyphs returned in each layout run, > * matching up the glyphs with the characters in the source text. > * We use the aSpacing argument to figure out where to place those >- * glyphs. It's important to note that since the string we're >- * working with is in UTF-8 while the spacing argument assumes >- * that offset will be part of the UTF-16 string. Logical >- * attributes in pango are in byte offsets in the UTF-8 string, so >- * we need to store the offsets based on the UTF-8 string. >+ * glyphs. > */ >- nscoord *utf8spacing = new nscoord[strlen(aText)]; >+ for (GSList *tmpList = aLine->runs; tmpList && tmpList->data; >+ tmpList = tmpList->next) { >+ PangoGlyphItem *glyph_item = (PangoGlyphItem *)tmpList->data; >+ PangoGlyphItemIter iter; >+ gboolean have_cluster; >+ PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs; >+ int residualWidth = 0; >+ >+ for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, aText); >+ have_cluster; >+ have_cluster = _pango_glyph_item_iter_next_cluster (&iter)) >+ { >+ int clusterOldWidth = 0; >+ int clusterNewWidth = 0; >+ int dir = iter.start_glyph < iter.end_glyph ? +1 : -1; >+ gboolean has_zero_width = FALSE; >+ >+ for (const char *p = iter.text + iter.start_index; >+ p < iter.text + iter.end_index; >+ p = g_utf8_next_char (p)) >+ clusterNewWidth += aSpacing[p - iter.text]; >+ >+ clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE); >+ >+ for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) { >+ if (!glyphs[i].geometry.width) >+ has_zero_width = TRUE; >+ clusterOldWidth += glyphs[i].geometry.width; >+ } >+ >+ /* if a zero-width glyph exists, don't touch the glyph widths. >+ * required for combining marks. ff thinks they have a width. >+ * instead, we charge the difference to the next space glyph. */ >+ if (has_zero_width) { >+ residualWidth += clusterNewWidth - clusterOldWidth; >+ continue; >+ } > >- if (aOrigString) { >- const gchar *curChar = aText; >- bzero(utf8spacing, sizeof(nscoord) * strlen(aText)); >- >- // Covert the utf16 spacing offsets to utf8 spacing offsets >- for (PRUint32 curOffset=0; curOffset < aLength; >- curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { >- utf8spacing[curChar - aText] = aSpacing[curOffset]; >+ /* If a space glyph is found, charge it whatever residual we >+ * have accumulated so far. */ >+ if (iter.end_index - iter.start_index == 1 && >+ *(iter.text + iter.start_index) == ' ') { >+ clusterNewWidth += residualWidth; >+ residualWidth = 0; >+ } >+ >+#ifndef PSPANGO >+ /* do some hinting for display */ >+ >+ if (clusterOldWidth % PANGO_SCALE == 0 && clusterNewWidth % PANGO_SCALE != 0) { >+ int tmp = clusterNewWidth; >+ clusterNewWidth = PANGO_PIXELS (clusterNewWidth) * PANGO_SCALE; >+ residualWidth += tmp - clusterNewWidth; >+ } >+#endif > >- if (IS_HIGH_SURROGATE(aOrigString[curOffset])) >- curOffset++; >+ /* find the first non-zero-width glyph and adjust its width */ >+ for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) >+ if (glyphs[i].geometry.width) { >+ glyphs[i].geometry.width += clusterNewWidth - clusterOldWidth; >+ break; >+ } > } > } >- else { >- memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength)); >- } >+} > >- gint curRun = 0; >+void >+nsFontMetricsPango::ApplySpacing(const PRUnichar *aText, >+ PRUint32 aLength, >+ PangoLayoutLine *aLine, >+ const nscoord *aSpacing) >+{ >+ if (!(aSpacing && *aSpacing)) >+ return; > >- for (GSList *tmpList = aLine->runs; tmpList && tmpList->data; >- tmpList = tmpList->next, curRun++) { >- PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data; >- gint tmpOffset = 0; >+ const char *utf8Text = pango_layout_get_text (aLine->layout); >+ int utf8Text_len = aLine->start_index + aLine->length; >+ >+ /* Since the string we're >+ * working with is in UTF-8 while the spacing argument assumes >+ * that offset will be part of the UTF-16 string. Logical >+ * attributes in pango are in byte offsets in the UTF-8 string, so >+ * we need to store the offsets based on the UTF-8 string. >+ */ >+ nscoord *utf8spacing = g_new0 (nscoord, utf8Text_len); > >- /* printf(" Rendering run %d: \"%s\"\n", curRun, >- &aText[layoutRun->item->offset]); */ >+ const gchar *curChar = utf8Text + aLine->start_index; > >- for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) { >- /* printf("glyph %d offset %d orig width %d new width %d\n", i, >- * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset, >- * layoutRun->glyphs->glyphs[i].geometry.width, >- * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE)); >- */ >- gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] >- * app2dev * PANGO_SCALE); >- layoutRun->glyphs->glyphs[i].geometry.width = thisOffset; >- tmpOffset += thisOffset; >- } >+ // Covert the utf16 spacing offsets to utf8 spacing offsets >+ for (PRUint32 curOffset=0; curOffset < aLength; >+ curOffset++, curChar = g_utf8_next_char(curChar)) { >+ utf8spacing[curChar - utf8Text] = aSpacing[curOffset]; > >- /* printf(" rendering at X coord %d\n", aX + offset); */ >- offset += tmpOffset; >+ if (IS_HIGH_SURROGATE(aText[curOffset])) >+ curOffset++; > } > >- gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine); >+ ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing); > >- delete[] utf8spacing; >+ g_free (utf8spacing); > } > > nsresult >@@ -1357,8 +1664,8 @@ nsFontMetricsPango::GetTextDimensionsInt > PRInt32 aNumBreaks, > nsTextDimensions& aDimensions, > PRInt32& aNumCharsFit, >- nsTextDimensions& aLastWordDimensions, >- nsRenderingContextGTK *aContext) >+ nsTextDimensions& aLastWordDimensions >+ CONTEXT_ARG_DEF) > { > NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array"); > >@@ -1404,7 +1711,7 @@ nsFontMetricsPango::GetTextDimensionsInt > // All the characters should fit > numChars = aLength - start; > breakIndex = aNumBreaks - 1; >- } >+ } > else { > breakIndex = prevBreakState_BreakIndex; > while (((breakIndex + 1) < aNumBreaks) && >@@ -1425,7 +1732,7 @@ nsFontMetricsPango::GetTextDimensionsInt > if ((1 == numChars) && (aString[start] == ' ')) > GetSpaceWidth(twWidth); > else if (numChars > 0) >- GetWidth(&aString[start], numChars, twWidth, aContext); >+ GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS); > > // See if the text fits > PRBool textFits = (twWidth + width) <= aAvailWidth; >@@ -1475,8 +1782,7 @@ nsFontMetricsPango::GetTextDimensionsInt > if ((1 == numChars) && (aString[start] == ' ')) > GetSpaceWidth(twWidth); > else if (numChars > 0) >- GetWidth(&aString[start], numChars, twWidth, >- aContext); >+ GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS); > width -= twWidth; > aNumCharsFit = start; > breakIndex--; >@@ -1498,9 +1804,16 @@ nsFontMetricsPango::GetTextDimensionsInt > } > > void >-nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout, >- const char *aString) >+nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout) > { >+ if (!mPangoSpaceWidth) >+ return; >+ >+ const char *aString = pango_layout_get_text (aLayout); >+ >+ if (pango_layout_get_line_count(aLayout) != 1) { >+ printf("Warning: more than one line!\n"); >+ } > PangoLayoutLine *line = pango_layout_get_line(aLayout, 0); > > gint curRun = 0; >@@ -1517,6 +1830,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa > } > } > >+PangoLayout* >+nsFontMetricsPango::GetLayout (const PRUnichar* aText, >+ PRUint32 aLength) >+{ >+ gchar* text; >+ gint length; >+ utf16_to_utf8 (aText, aLength, text, length); >+ >+ PangoLayout *layout = pango_layout_new(mPangoContext); >+ pango_layout_set_text (layout, text, length); >+ FixupSpaceWidths (layout); >+ >+ g_free ((gpointer) text); >+ >+ return layout; >+} >+ >+PangoLayout* >+nsFontMetricsPango::GetLayout (const gchar* aText, >+ PRInt32 aLength) >+{ >+ gboolean has_nul = FALSE; >+ int i; >+ >+ for (i = 0; i < aLength; i++) >+ if (!aText[i]) { >+ has_nul = TRUE; >+ break; >+ } >+ >+ if (has_nul) { >+ /* Pango doesn't correctly handle nuls. We convert them to 0xff. */ >+ >+ char *p = (char *) g_memdup (aText, aLength); >+ >+ /* don't need to reset i */ >+ for (; i < aLength; i++) >+ if (!p[i]) >+ p[i] = (char) 0xff; >+ >+ aText = p; >+ } >+ >+ PangoLayout *layout = pango_layout_new(mPangoContext); >+ pango_layout_set_text (layout, aText, aLength); >+ FixupSpaceWidths (layout); >+ >+ if (has_nul) >+ g_free ((gpointer) aText); >+ >+ return layout; >+} >+ >+static void >+utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length) >+{ >+ gboolean need_copy = FALSE; >+ int i; >+ >+ for (i = 0; i < aLength; i++) { >+ if (!aText[i] || IS_LOW_SURROGATE (aText[i])) >+ need_copy = TRUE; >+ else if (IS_HIGH_SURROGATE (aText[i])) { >+ if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1])) >+ i++; >+ else >+ need_copy = TRUE; >+ } >+ } >+ >+ if (need_copy) { >+ >+ /* Pango doesn't correctly handle nuls. We convert them to 0xff. */ >+ /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */ >+ >+ PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0])); >+ >+ /* don't need to reset i */ >+ for (i = 0; i < aLength; i++) { >+ if (!p[i] || IS_LOW_SURROGATE (p[i])) >+ p[i] = 0xFFFD; >+ else if (IS_HIGH_SURROGATE (p[i])) { >+ if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1])) >+ i++; >+ else >+ p[i] = 0xFFFD; >+ } >+ } >+ >+ aText = p; >+ } >+ >+ glong items_written; >+ text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL); >+ length = items_written; >+ >+ if (need_copy) >+ g_free ((gpointer) aText); >+ >+} >+ > /* static */ > PangoLanguage * > GetPangoLanguage(nsIAtom *aLangGroup) >--- mozilla/gfx/src/gtk/mozilla-decoder.cpp.printing 2007-07-03 15:40:51.000000000 +0200 >+++ mozilla/gfx/src/gtk/mozilla-decoder.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -36,14 +36,11 @@ > * > * ***** END LICENSE BLOCK ***** */ > >-#define PANGO_ENABLE_BACKEND >-#define PANGO_ENABLE_ENGINE >- >-#include "mozilla-decoder.h" >+#include <pango/pangofc-decoder.h> > #include <pango/pangofc-fontmap.h> > #include <pango/pangofc-font.h> >-#include <gdk/gdkpango.h> > >+#include "mozilla-decoder.h" > #include "nsString.h" > #include "nsIPersistentProperties2.h" > #include "nsNetUtil.h" >@@ -52,11 +49,39 @@ > #include "nsICharRepresentable.h" > #include "nsCompressedCharMap.h" > >+#ifdef PSPANGO >+#define MozillaDecoder MozillaDecoderPS >+#define MozillaDecoderClass MozillaDecoderPSClass >+#endif >+ >+static GType mozilla_decoder_get_type (void); >+ >+#define MOZILLA_TYPE_DECODER (mozilla_decoder_get_type()) >+#define MOZILLA_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaDecoder)) >+#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER)) >+ >+typedef struct _MozillaDecoder MozillaDecoder; >+typedef struct _MozillaDecoderClass MozillaDecoderClass; >+ >+#define MOZILLA_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaDecoderClass)) >+#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER)) >+#define MOZILLA_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderClass)) >+ >+struct _MozillaDecoder >+{ >+ PangoFcDecoder parent_instance; >+}; >+ >+struct _MozillaDecoderClass >+{ >+ PangoFcDecoderClass parent_class; >+}; >+ > #undef DEBUG_CUSTOM_ENCODER > > G_DEFINE_TYPE (MozillaDecoder, mozilla_decoder, PANGO_TYPE_FC_DECODER) > >-MozillaDecoder *mozilla_decoder_new (void); >+static MozillaDecoder *mozilla_decoder_new (void); > > static FcCharSet *mozilla_decoder_get_charset (PangoFcDecoder *decoder, > PangoFcFont *fcfont); >@@ -91,12 +116,12 @@ GHashTable *encoder_hash = NULL; > GHashTable *cmap_hash = NULL; > GHashTable *wide_hash = NULL; > >-void >+static void > mozilla_decoder_init (MozillaDecoder *decoder) > { > } > >-void >+static void > mozilla_decoder_class_init (MozillaDecoderClass *klass) > { > GObjectClass *object_class = G_OBJECT_CLASS(klass); >@@ -110,14 +135,14 @@ mozilla_decoder_class_init (MozillaDecod > g_type_class_add_private (object_class, sizeof (MozillaDecoderPrivate)); > } > >-MozillaDecoder * >+static MozillaDecoder * > mozilla_decoder_new(void) > { > return (MozillaDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL); > } > > #ifdef DEBUG_CUSTOM_ENCODER >-void >+static void > dump_hash(char *key, char *val, void *arg) > { > printf("%s -> %s\n", key, val); >@@ -136,21 +161,21 @@ dump_hash(char *key, char *val, void *ar > * Return value: zero on success, not zero on failure. > * > **/ >- > int >-mozilla_decoders_init(void) >+mozilla_decoders_init(PangoFontMap *fontmap) > { >- static PRBool initialized = PR_FALSE; >- if (initialized) >- return 0; >+ static GQuark init_quark; > >- PangoContext* context = gdk_pango_context_get (); >- PangoFontMap* fontmap = pango_context_get_font_map (context); >- g_object_unref (context); >- > if (!PANGO_IS_FC_FONT_MAP (fontmap)) > return -1; > >+ if (G_UNLIKELY (!init_quark)) { >+ init_quark = g_quark_from_static_string ("mozilla-decoders-set"); >+ } >+ >+ if (G_LIKELY (g_object_get_qdata ((GObject *)fontmap, init_quark))) >+ return 0; >+ > encoder_hash = g_hash_table_new(g_str_hash, g_str_equal); > cmap_hash = g_hash_table_new(g_str_hash, g_str_equal); > wide_hash = g_hash_table_new(g_str_hash, g_str_equal); >@@ -219,7 +244,7 @@ mozilla_decoders_init(void) > NULL, > NULL); > >- initialized = PR_TRUE; >+ g_object_set_qdata ((GObject *)fontmap, init_quark, GINT_TO_POINTER (1)); > > #ifdef DEBUG_CUSTOM_ENCODER > printf("*** encoders\n"); >@@ -235,7 +260,7 @@ mozilla_decoders_init(void) > return -1; > } > >-FcCharSet * >+static FcCharSet * > mozilla_decoder_get_charset (PangoFcDecoder *decoder, > PangoFcFont *fcfont) > { >@@ -283,7 +308,7 @@ mozilla_decoder_get_charset (PangoFcDeco > return priv->charset; > } > >-PangoGlyph >+static PangoGlyph > mozilla_decoder_get_glyph (PangoFcDecoder *decoder, > PangoFcFont *fcfont, > guint32 wc) >@@ -344,7 +369,7 @@ mozilla_decoder_get_glyph (PangoFcDeco > return retval; > } > >-PangoFcDecoder * >+static PangoFcDecoder * > mozilla_find_decoder (FcPattern *pattern, gpointer user_data) > { > // Compare the family name of the font that's been opened to see >--- mozilla/gfx/src/gtk/Makefile.in.printing 2005-04-26 06:46:13.000000000 +0200 >+++ mozilla/gfx/src/gtk/Makefile.in 2007-07-03 15:40:51.000000000 +0200 >@@ -127,6 +127,8 @@ ifdef MOZ_ENABLE_PANGO > CPPSRCS += \ > nsFontMetricsPango.cpp \ > mozilla-decoder.cpp >+CSRCS += \ >+ pango-renderer.c > endif > > ifdef MOZ_ENABLE_GTK >--- mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp.printing 2005-03-28 04:14:17.000000000 +0200 >+++ mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -143,11 +143,24 @@ NS_IsXftEnabled(void) > PRBool > NS_IsPangoEnabled(void) > { >- char *val = PR_GetEnv("MOZ_DISABLE_PANGO"); >- if (val) >- return FALSE; >+ static PRBool beenHere; >+ static PRBool pangoEnabled; > >- return TRUE; >+ if (!beenHere) { >+ beenHere = PR_TRUE; >+ >+ char *val = PR_GetEnv("MOZ_DISABLE_PANGO"); >+ pangoEnabled = !(val); >+ >+ if (pangoEnabled) { >+ nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID); >+ if (prefService) >+ prefService->SetDefaultCharPref("general.useragent.extra.pango", >+ "pango-text"); >+ } >+ } >+ >+ return pangoEnabled; > } > > #endif >--- mozilla/gfx/src/freetype/nsFreeType.cpp.printing 2005-07-13 20:21:10.000000000 +0200 >+++ mozilla/gfx/src/freetype/nsFreeType.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -123,6 +123,8 @@ FtFuncList nsFreeType2::FtFuncs [] = { > // #endif > {"FT_Get_First_Char", NS_FT2_OFFSET(nsFT_Get_First_Char), PR_FALSE}, > {"FT_Get_Next_Char", NS_FT2_OFFSET(nsFT_Get_Next_Char), PR_FALSE}, >+ {"FT_Has_PS_Glyph_Names", NS_FT2_OFFSET(nsFT_Has_PS_Glyph_Names), PR_FALSE}, >+ {"FT_Get_Glyph_Name", NS_FT2_OFFSET(nsFT_Get_Glyph_Name), PR_TRUE}, > {nsnull, 0, 0} > }; > >@@ -388,6 +390,22 @@ nsFreeType2::GetNextChar(FT_Face face, F > } > > NS_IMETHODIMP >+nsFreeType2::HasPSGlyphNames(FT_Face face, FT_Int *result) >+{ >+ // call the FreeType2 function via the function pointer >+ *result = nsFT_Has_PS_Glyph_Names(face); >+ return NS_OK; >+} >+ >+NS_IMETHODIMP >+nsFreeType2::GetGlyphName(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max) >+{ >+ // call the FreeType2 function via the function pointer >+ FT_Error error = nsFT_Get_Glyph_Name(face, glyph_index, buffer, buffer_max); >+ return error ? NS_ERROR_FAILURE : NS_OK; >+} >+ >+NS_IMETHODIMP > nsFreeType2::SupportsExtFunc(PRBool *res) > { > *res = gHasExtFunc; >--- mozilla/gfx/src/freetype/nsFreeType.h.printing 2005-05-01 19:36:19.000000000 +0200 >+++ mozilla/gfx/src/freetype/nsFreeType.h 2007-07-03 15:40:51.000000000 +0200 >@@ -52,6 +52,7 @@ > #include FT_CACHE_H > #include FT_CACHE_IMAGE_H > #include FT_TRUETYPE_TABLES_H >+#include FT_TYPE1_TABLES_H > #include "nsIFreeType2.h" > > typedef struct FT_FaceRec_* FT_Face; >@@ -138,6 +139,8 @@ typedef FT_Error (*FT_Glyph_To_Bitmap_t) > > typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face, FT_UInt*); > typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face, FT_ULong, FT_UInt*); >+typedef FT_Int (*FT_Has_PS_Glyph_Names_t)(FT_Face); >+typedef FT_Error (*FT_Get_Glyph_Name_t)(FT_Face, FT_UInt, FT_Pointer, FT_UInt); > > class nsFreeTypeFace; > >@@ -193,11 +196,13 @@ protected: > // #endif > FT_Get_First_Char_t nsFT_Get_First_Char; > FT_Get_Next_Char_t nsFT_Get_Next_Char; >+ FT_Has_PS_Glyph_Names_t nsFT_Has_PS_Glyph_Names; >+ FT_Get_Glyph_Name_t nsFT_Get_Glyph_Name; > > // this array needs to be big enough to hold all the function pointers > // plus one extra for the null at the end > // #ifdef MOZ_SVG >- static FtFuncList FtFuncs[24]; >+ static FtFuncList FtFuncs[28]; > // #else > // static FtFuncList FtFuncs[20]; > // #endif >--- mozilla/gfx/src/ps/nsPostScriptObj.cpp.printing 2005-07-26 17:54:18.000000000 +0200 >+++ mozilla/gfx/src/ps/nsPostScriptObj.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -47,6 +47,10 @@ > * 10/09/2000 IPLabs Linux Team True Unicode glyps support added. > */ > >+#ifdef MOZ_ENABLE_PANGO >+#define PANGO_ENABLE_BACKEND >+#endif >+ > #include "gfx-config.h" > > #define FORCE_PR_LOG /* Allow logging in the release build */ >@@ -87,6 +91,12 @@ > #include <errno.h> > #include <sys/wait.h> > >+#ifdef MOZ_ENABLE_PANGO >+#ifndef PANGO_GLYPH_EMPTY >+#define PANGO_GLYPH_EMPTY 0 >+#endif >+#endif >+ > #ifdef PR_LOGGING > static PRLogModuleInfo *nsPostScriptObjLM = PR_NewLogModule("nsPostScriptObj"); > #endif /* PR_LOGGING */ >@@ -2061,34 +2071,98 @@ nsPostScriptObj::show(const PRUnichar* t > > #if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) > void >-nsPostScriptObj::show(const PRUnichar* aTxt, int aLen, >- const nsAFlatString& aCharList, PRUint16 aSubFontIdx) >+/*nsPostScriptObj::show(const PRUnichar* aTxt, int aLen, >+ const nsAFlatString& aCharList, PRUint16 aSubFontIdx) */ >+nsPostScriptObj::show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset, >+ PRUint16 aSubFontIdx) > { >- int i; >+ PRUint32 i; > fputc('<', mScriptFP); > >- const PRUint16 subFontSize = nsPSFontGenerator::kSubFontSize; >- >- // the character repertoire of a subfont (255 characters max) >- const nsAString& repertoire = >- Substring(aCharList, aSubFontIdx * subFontSize, >- PR_MIN(subFontSize, >- aCharList.Length() - aSubFontIdx * subFontSize)); >- >- for (i = 0; i < aLen; i++) { >- // XXX This is a little inefficient, but printing is not perf. critical. >- NS_ASSERTION(repertoire.FindChar(aTxt[i]) != kNotFound, >- "character is not covered by this subfont"); >- >- // Type 1 encoding vector has 256 slots, but the 0-th slot is >- // reserved for /.notdef so that we use the 1st through 255th slots >- // for actual characters (hence '+ 1') >- fprintf(mScriptFP, "%02x", repertoire.FindChar(aTxt[i]) + 1); >+ for (i = 0; i < aGlyphs->Count(); i++) { >+ PRUint32 glyph = aGlyphs->ValueAt(i); >+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph)); > } >+ > fputs("> show\n", mScriptFP); > } > #endif > >+#ifdef MOZ_ENABLE_PANGO >+void >+nsPostScriptObj::show(const PangoGlyphString *glyphs, float zoom, >+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx) >+{ >+ PRUint32 i, start; >+ int horiz = 1; >+ int x_off = 0, y_off = 0; >+ >+ /* skip inital empty glyphs */ >+ for (i = 0; i < glyphs->num_glyphs && glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY; i++) >+ x_off += glyphs->glyphs[i].geometry.width; >+ start = i; >+ >+ if (start >= glyphs->num_glyphs) >+ return; >+ >+ x_off += glyphs->glyphs[start].geometry.x_offset; >+ y_off += glyphs->glyphs[start].geometry.y_offset; >+ /* do we need an initial move? */ >+ if (x_off || y_off) { >+ rmoveto (NSToCoordRound (zoom * x_off / PANGO_SCALE), >+ NSToCoordRound (zoom * y_off / PANGO_SCALE)); >+ } >+ >+ fputc('<', mScriptFP); >+ >+ /* write the glyphs out. see if it's horizontal */ >+ for (i = start; i < glyphs->num_glyphs; i++) { >+ PRUint32 glyph = glyphs->glyphs[i].glyph; >+ >+ if (glyph == PANGO_GLYPH_EMPTY) >+ continue; >+ >+ fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph)); >+ if (glyphs->glyphs[i].geometry.y_offset) >+ horiz = 0; >+ } >+ >+ /* write out the advance vector and show */ >+ i = start; >+ x_off = -glyphs->glyphs[i].geometry.x_offset + glyphs->glyphs[i].geometry.width; >+ y_off = -glyphs->glyphs[i].geometry.y_offset; >+ i++; >+ fputs(">\n[", mScriptFP); >+ >+ for (; i < glyphs->num_glyphs; i++) { >+ PangoGlyphInfo *gli = glyphs->glyphs + i; >+ >+ if (gli->glyph == PANGO_GLYPH_EMPTY) { >+ x_off += gli->geometry.width; >+ continue; >+ } >+ >+ x_off += gli->geometry.x_offset; >+ fprintf(mScriptFP, "%d ", NSToCoordRound (zoom * x_off / PANGO_SCALE)); >+ x_off = -gli->geometry.x_offset + gli->geometry.width; >+ >+ if (horiz) >+ continue; >+ >+ y_off += gli->geometry.y_offset; >+ fprintf(mScriptFP, "%d ", NSToCoordRound (zoom * y_off / PANGO_SCALE)); >+ y_off = -gli->geometry.y_offset; >+ } >+ fprintf(mScriptFP, "%d", NSToCoordRound (zoom * x_off / PANGO_SCALE)); >+ if (horiz) >+ fputs("] xshow\n", mScriptFP); >+ else { >+ fprintf(mScriptFP, " %d", NSToCoordRound (zoom * y_off / PANGO_SCALE)); >+ fputs("] xyshow\n", mScriptFP); >+ } >+} >+#endif >+ > /** --------------------------------------------------- > * See documentation in nsPostScriptObj.h > * @update 2/1/99 dwc >@@ -2101,6 +2175,16 @@ nsPostScriptObj::moveto(nscoord x, nscoo > > /** --------------------------------------------------- > * See documentation in nsPostScriptObj.h >+ * @update 10/20/06 behdad >+ */ >+void >+nsPostScriptObj::rmoveto(nscoord x, nscoord y) >+{ >+ fprintf(mScriptFP, "%d %d rmoveto\n", x, y); >+} >+ >+/** --------------------------------------------------- >+ * See documentation in nsPostScriptObj.h > * @update 2/1/99 dwc > */ > void >--- mozilla/gfx/src/ps/nsFontMetricsPS.h.printing 2005-06-28 20:29:10.000000000 +0200 >+++ mozilla/gfx/src/ps/nsFontMetricsPS.h 2007-07-03 15:40:51.000000000 +0200 >@@ -66,6 +66,7 @@ > #endif > #include "nsVoidArray.h" > #include "nsHashtable.h" >+#include "nsValueArray.h" > > class nsPSFontGenerator; > class nsDeviceContextPS; >@@ -108,6 +109,65 @@ public: > NS_IMETHOD GetFontHandle(nsFontHandle &aHandle); > NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength); > NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength); >+ >+ NS_IMETHOD GetTextDimensions(const char* aString, >+ PRUint32 aLength, >+ nsTextDimensions& aDimensions); >+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, >+ PRUint32 aLength, >+ nsTextDimensions& aDimensions, >+ PRInt32* aFontID); >+ NS_IMETHOD GetTextDimensions(const char* aString, >+ PRInt32 aLength, >+ PRInt32 aAvailWidth, >+ PRInt32* aBreaks, >+ PRInt32 aNumBreaks, >+ nsTextDimensions& aDimensions, >+ PRInt32& aNumCharsFit, >+ nsTextDimensions& aLastWordDimensions, >+ PRInt32* aFontID); >+ NS_IMETHOD GetTextDimensions(const PRUnichar* aString, >+ PRInt32 aLength, >+ PRInt32 aAvailWidth, >+ PRInt32* aBreaks, >+ PRInt32 aNumBreaks, >+ nsTextDimensions& aDimensions, >+ PRInt32& aNumCharsFit, >+ nsTextDimensions& aLastWordDimensions, >+ PRInt32* aFontID); >+#ifdef MOZ_MATHML >+ NS_IMETHOD GetBoundingMetrics(const char *aString, PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics); >+ NS_IMETHOD GetBoundingMetrics(const PRUnichar *aString, >+ PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics, >+ PRInt32 *aFontID); >+#endif /* MOZ_MATHML */ >+ >+ NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext); >+ NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ PRInt32 aFontID, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext); >+ >+protected: >+ PRInt32 DrawString(const char *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, nsFontPS* aFontPS, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext); >+ PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength, >+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext); >+ >+public: >+ >+ virtual PRUint32 GetHints (void) { return 0; } >+ > > inline void SetXHeight(nscoord aXHeight) { mXHeight = aXHeight; }; > inline void SetSuperscriptOffset(nscoord aSuperscriptOffset) { mSuperscriptOffset = aSuperscriptOffset; }; >@@ -455,16 +515,14 @@ public: > nsPSFontGenerator(); > virtual ~nsPSFontGenerator(); > virtual void GeneratePSFont(FILE* aFile); >- PRInt32 AddToSubset(PRUnichar aChar); >- nsString *GetSubset(); >+ PRInt32 AddToGlyphSubset(PRUint32 aGlyph); >+ PRInt32 InSubsetIndexOf(PRUint32 aGlyph); > > // 256 (PS type 1 encoding vector size) - 1 (1 is for mandatory /.notdef) > const static PRUint16 kSubFontSize; > > protected: >- // XXX To support non-BMP characters, we may have to use >- // nsValueArray with PRUint32 >- nsString mSubset; >+ nsValueArray *mGlyphSubset; > }; > > >--- mozilla/gfx/src/ps/nsRenderingContextPS.cpp.printing 2005-03-04 08:39:27.000000000 +0100 >+++ mozilla/gfx/src/ps/nsRenderingContextPS.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -251,6 +251,8 @@ nsRenderingContextPS :: GetDrawingSurfac > NS_IMETHODIMP > nsRenderingContextPS :: GetHints(PRUint32& aResult) > { >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ aResult = metrics->GetHints (); > return NS_OK; > } > >@@ -1006,8 +1008,11 @@ nsRenderingContextPS::GetTextDimensions( > nsTextDimensions& aLastWordDimensions, > PRInt32* aFontID) > { >- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions"); >- return NS_ERROR_NOT_IMPLEMENTED; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks, >+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID); > } > > NS_IMETHODIMP >@@ -1021,43 +1026,31 @@ nsRenderingContextPS::GetTextDimensions( > nsTextDimensions& aLastWordDimensions, > PRInt32* aFontID) > { >- NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions"); >- return NS_ERROR_NOT_IMPLEMENTED; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks, >+ aDimensions, aNumCharsFit, aLastWordDimensions, aFontID); > } > > NS_IMETHODIMP > nsRenderingContextPS :: GetTextDimensions(const char* aString, PRUint32 aLength, > nsTextDimensions& aDimensions) > { >- nsresult rv = NS_ERROR_FAILURE; >- >- if (mFontMetrics) { >- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >- metrics->GetStringWidth(aString, aDimensions.width, aLength); >- metrics->GetMaxAscent(aDimensions.ascent); >- metrics->GetMaxDescent(aDimensions.descent); >- rv = NS_OK; >- } >- >- return rv; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetTextDimensions (aString, aLength, aDimensions); > } > > NS_IMETHODIMP > nsRenderingContextPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, > nsTextDimensions& aDimensions, PRInt32* aFontID) > { >- nsresult rv = NS_ERROR_FAILURE; >- >- if (mFontMetrics) { >- nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >- metrics->GetStringWidth(aString, aDimensions.width, aLength); >- //XXX temporary - bug 96609 >- metrics->GetMaxAscent(aDimensions.ascent); >- metrics->GetMaxDescent(aDimensions.descent); >- rv = NS_OK; >- } >- >- return rv; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetTextDimensions (aString, aLength, aDimensions, aFontID); > } > > /** --------------------------------------------------- >@@ -1073,47 +1066,7 @@ nsRenderingContextPS :: DrawString(const > > nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); > NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >- >- // When FT2 printing is enabled, we don't need to set langgroup >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) { >-#endif >- nsCOMPtr<nsIAtom> langGroup; >- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup)); >- mPSObj->setlanggroup(langGroup); >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >- } >-#endif >- >- if (aLength == 0) >- return NS_OK; >- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics); >- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); >- fontPS->SetupFont(this); >- >- PRUint32 i, start = 0; >- for (i=0; i<aLength; i++) { >- nsFontPS* fontThisChar; >- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics); >- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); >- if (fontThisChar != fontPS) { >- // draw text up to this point >- aX += DrawString(aString+start, i-start, aX, aY, fontPS, >- aSpacing?aSpacing+start:nsnull); >- start = i; >- >- // setup for following text >- fontPS = fontThisChar; >- fontPS->SetupFont(this); >- } >- } >- >- // draw the last part >- if (aLength-start) >- DrawString(aString+start, aLength-start, aX, aY, fontPS, >- aSpacing?aSpacing+start:nsnull); >- >- return NS_OK; >+ return metrics->DrawString (aString, aLength, aX, aY, aSpacing, this); > } > > /** --------------------------------------------------- >@@ -1129,110 +1082,7 @@ nsRenderingContextPS :: DrawString(const > > nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); > NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >- >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >- // When FT2 printing is enabled, we don't need to set langgroup >- if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) { >-#endif >- nsCOMPtr<nsIAtom> langGroup = nsnull; >- mFontMetrics->GetLangGroup(getter_AddRefs(langGroup)); >- mPSObj->setlanggroup(langGroup); >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >- } >-#endif >- >- /* build up conversion table */ >- mPSObj->preshow(aString, aLength); >- >- if (aLength == 0) >- return NS_OK; >- nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics); >- NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); >- fontPS->SetupFont(this); >- >- PRUint32 i, start = 0; >- for (i=0; i<aLength; i++) { >- nsFontPS* fontThisChar; >- fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics); >- NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); >- if (fontThisChar != fontPS) { >- // draw text up to this point >- aX += DrawString(aString+start, i-start, aX, aY, fontPS, >- aSpacing?aSpacing+start:nsnull); >- start = i; >- >- // setup for following text >- fontPS = fontThisChar; >- fontPS->SetupFont(this); >- } >- } >- >- // draw the last part >- if (aLength-start) >- DrawString(aString+start, aLength-start, aX, aY, fontPS, >- aSpacing?aSpacing+start:nsnull); >- >- return NS_OK; >-} >- >-PRInt32 >-nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength, >- nscoord &aX, nscoord &aY, nsFontPS* aFontPS, >- const nscoord* aSpacing) >-{ >- nscoord width = 0; >- PRInt32 x = aX; >- PRInt32 y = aY; >- >- PRInt32 dxMem[500]; >- PRInt32* dx0 = 0; >- if (aSpacing) { >- dx0 = dxMem; >- if (aLength > 500) { >- dx0 = new PRInt32[aLength]; >- NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY); >- } >- mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0); >- } >- >- mTranMatrix->TransformCoord(&x, &y); >- width = aFontPS->DrawString(this, x, y, aString, aLength); >- >- if ((aSpacing) && (dx0 != dxMem)) { >- delete [] dx0; >- } >- >- return width; >-} >- >- >-PRInt32 >-nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength, >- nscoord aX, nscoord aY, nsFontPS* aFontPS, >- const nscoord* aSpacing) >-{ >- nscoord width = 0; >- PRInt32 x = aX; >- PRInt32 y = aY; >- >- if (aSpacing) { >- // Slow, but accurate rendering >- const PRUnichar* end = aString + aLength; >- while (aString < end){ >- x = aX; >- y = aY; >- mTranMatrix->TransformCoord(&x, &y); >- aFontPS->DrawString(this, x, y, aString, 1); >- aX += *aSpacing++; >- aString++; >- } >- width = aX; >- } else { >- mTranMatrix->TransformCoord(&x, &y); >- width = aFontPS->DrawString(this, x, y, aString, aLength); >- } >- >- return width; >+ return metrics->DrawString (aString, aLength, aX, aY, aFontID, aSpacing, this); > } > > /** --------------------------------------------------- >@@ -1346,8 +1196,10 @@ nsRenderingContextPS::GetBoundingMetrics > PRUint32 aLength, > nsBoundingMetrics& aBoundingMetrics) > { >- // Fill me up >- return NS_ERROR_NOT_IMPLEMENTED; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics); > } > > /** >@@ -1359,8 +1211,10 @@ nsRenderingContextPS::GetBoundingMetrics > nsBoundingMetrics& aBoundingMetrics, > PRInt32* aFontID) > { >- // Fill me up >- return NS_ERROR_NOT_IMPLEMENTED; >+ NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER); >+ nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get()); >+ NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE); >+ return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics, aFontID); > } > #endif /* MOZ_MATHML */ > >--- mozilla/gfx/src/ps/nsPostScriptObj.h.printing 2005-05-08 17:01:20.000000000 +0200 >+++ mozilla/gfx/src/ps/nsPostScriptObj.h 2007-07-03 15:40:51.000000000 +0200 >@@ -57,9 +57,15 @@ > #include "nsIPersistentProperties2.h" > #include "nsTempfilePS.h" > #include "nsEPSObjectPS.h" >+#ifdef MOZ_ENABLE_PANGO >+#include <pango/pango.h> >+#endif >+ > >+class nsPSFontGenerator; > class nsIImage; > class nsIAtom; >+class nsValueArray; > #endif > > #include <stdio.h> >@@ -217,6 +223,14 @@ public: > */ > void moveto(nscoord aX, nscoord aY); > /** --------------------------------------------------- >+ * Move relative to the current point >+ * @update 10/20/2006 behdad >+ * @param aX X coordinate >+ * aY Y coordinate >+ * @return VOID >+ */ >+ void rmoveto(nscoord aX, nscoord aY); >+ /** --------------------------------------------------- > * Add a line to the current path, from the current point > * to the specified point. > * @update 9/30/2003 >@@ -346,12 +360,24 @@ public: > */ > void show(const PRUnichar* aText, int aLen, const char *aAlign, int aType); > /** --------------------------------------------------- >- * This version takes a PRUnichar string, a font subset string >- * for freetype printing and a subfont index >+ * This version of show takes an array of glyphs, subfont and subfont index >+ * to render and is used for freetype and xft printing. > * @update 2/15/2005 jshin@mailaps.org >+ * @update 6/7/2005 blizzard@mozilla.org > */ >- void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList, >+ void show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset, > PRUint16 aSubFontIdx); >+ /*void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList, >+ PRUint16 aSubFontIdx); */ >+#ifdef MOZ_ENABLE_PANGO >+ /** --------------------------------------------------- >+ * This version of show takes a pango glyph string, subfont and subfont index >+ * to render and is used for pango printing. >+ * @update 10/20/2006 behdad@behdad.org >+ */ >+ void show(const PangoGlyphString *glyphs, float zoom, >+ nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx); >+#endif > /** --------------------------------------------------- > * set the clipping path to the current path using the winding rule > * @update 2/1/99 dwc >--- mozilla/gfx/src/ps/nsRenderingContextPS.h.printing 2004-09-20 08:46:16.000000000 +0200 >+++ mozilla/gfx/src/ps/nsRenderingContextPS.h 2007-07-03 15:40:51.000000000 +0200 >@@ -154,6 +154,10 @@ public: > NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength, > nscoord& aWidth, PRInt32 *aFontID); > >+ nsTransform2D *GetTranMatrix() { >+ return mTranMatrix; >+ } >+ > NS_IMETHOD DrawString(const char *aString, PRUint32 aLength, > nscoord aX, nscoord aY, > const nscoord* aSpacing); >@@ -164,13 +168,6 @@ public: > NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY, > PRInt32 aFontID, > const nscoord* aSpacing); >-protected: >- PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength, >- nscoord aX, nscoord aY, nsFontPS* aFontPS, >- const nscoord* aSpacing); >- PRInt32 DrawString(const char *aString, PRUint32 aLength, >- nscoord &aX, nscoord &aY, nsFontPS* aFontPS, >- const nscoord* aSpacing); > public: > > NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength, >--- mozilla/gfx/src/ps/nsFontMetricsPS.cpp.printing 2007-01-04 00:57:04.000000000 +0100 >+++ mozilla/gfx/src/ps/nsFontMetricsPS.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -461,6 +461,239 @@ nsFontMetricsPS :: GetStringWidth(const > return NS_OK; > } > >+nsresult >+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext) >+{ >+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); >+ // When FT2 printing is enabled, we don't need to set langgroup >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) { >+#endif >+ nsCOMPtr<nsIAtom> langGroup; >+ GetLangGroup(getter_AddRefs(langGroup)); >+ psObj->setlanggroup(langGroup); >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+ } >+#endif >+ >+ if (aLength == 0) >+ return NS_OK; >+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this); >+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); >+ fontPS->SetupFont(aContext); >+ >+ PRUint32 i, start = 0; >+ for (i=0; i<aLength; i++) { >+ nsFontPS* fontThisChar; >+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this); >+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); >+ if (fontThisChar != fontPS) { >+ // draw text up to this point >+ aX += DrawString(aString+start, i-start, aX, aY, fontPS, >+ aSpacing?aSpacing+start:nsnull, aContext); >+ start = i; >+ >+ // setup for following text >+ fontPS = fontThisChar; >+ fontPS->SetupFont(aContext); >+ } >+ } >+ >+ // draw the last part >+ if (aLength-start) >+ DrawString(aString+start, aLength-start, aX, aY, fontPS, >+ aSpacing?aSpacing+start:nsnull, aContext); >+ >+ return NS_OK; >+} >+ >+nsresult >+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, >+ PRInt32 aFontID, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext) >+{ >+ nsPostScriptObj* psObj = aContext->GetPostScriptObj(); >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+ // When FT2 printing is enabled, we don't need to set langgroup >+ if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) { >+#endif >+ nsCOMPtr<nsIAtom> langGroup = nsnull; >+ GetLangGroup(getter_AddRefs(langGroup)); >+ psObj->setlanggroup(langGroup); >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+ } >+#endif >+ >+ /* build up conversion table */ >+ psObj->preshow(aString, aLength); >+ >+ if (aLength == 0) >+ return NS_OK; >+ nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this); >+ NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE); >+ fontPS->SetupFont(aContext); >+ >+ PRUint32 i, start = 0; >+ for (i=0; i<aLength; i++) { >+ nsFontPS* fontThisChar; >+ fontThisChar = nsFontPS::FindFont(aString[i], Font(), this); >+ NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE); >+ if (fontThisChar != fontPS) { >+ // draw text up to this point >+ aX += DrawString(aString+start, i-start, aX, aY, fontPS, >+ aSpacing?aSpacing+start:nsnull, aContext); >+ start = i; >+ >+ // setup for following text >+ fontPS = fontThisChar; >+ fontPS->SetupFont(aContext); >+ } >+ } >+ >+ // draw the last part >+ if (aLength-start) >+ DrawString(aString+start, aLength-start, aX, aY, fontPS, >+ aSpacing?aSpacing+start:nsnull, aContext); >+ >+ return NS_OK; >+} >+ >+PRInt32 >+nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength, >+ nscoord aX, nscoord aY, nsFontPS* aFontPS, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext) >+{ >+ nscoord width = 0; >+ PRInt32 x = aX; >+ PRInt32 y = aY; >+ >+ PRInt32 dxMem[500]; >+ PRInt32* dx0 = 0; >+ if (aSpacing) { >+ dx0 = dxMem; >+ if (aLength > 500) { >+ dx0 = new PRInt32[aLength]; >+ NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY); >+ } >+ aContext->GetTranMatrix()->ScaleXCoords(aSpacing, aLength, dx0); >+ } >+ >+ aContext->GetTranMatrix()->TransformCoord(&x, &y); >+ width = aFontPS->DrawString(aContext, x, y, aString, aLength); >+ >+ if ((aSpacing) && (dx0 != dxMem)) { >+ delete [] dx0; >+ } >+ >+ return width; >+} >+ >+ >+PRInt32 >+nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength, >+ nscoord &aX, nscoord &aY, nsFontPS* aFontPS, >+ const nscoord* aSpacing, >+ nsRenderingContextPS *aContext) >+{ >+ nscoord width = 0; >+ PRInt32 x = aX; >+ PRInt32 y = aY; >+ >+ if (aSpacing) { >+ // Slow, but accurate rendering >+ const PRUnichar* end = aString + aLength; >+ while (aString < end){ >+ x = aX; >+ y = aY; >+ aContext->GetTranMatrix()->TransformCoord(&x, &y); >+ aFontPS->DrawString(aContext, x, y, aString, 1); >+ aX += *aSpacing++; >+ aString++; >+ } >+ width = aX; >+ } else { >+ aContext->GetTranMatrix()->TransformCoord(&x, &y); >+ width = aFontPS->DrawString(aContext, x, y, aString, aLength); >+ } >+ >+ return width; >+} >+ >+NS_IMETHODIMP >+nsFontMetricsPS::GetTextDimensions(const char* aString, >+ PRInt32 aLength, >+ PRInt32 aAvailWidth, >+ PRInt32* aBreaks, >+ PRInt32 aNumBreaks, >+ nsTextDimensions& aDimensions, >+ PRInt32& aNumCharsFit, >+ nsTextDimensions& aLastWordDimensions, >+ PRInt32* aFontID) >+{ >+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions"); >+ return NS_ERROR_NOT_IMPLEMENTED; >+} >+ >+NS_IMETHODIMP >+nsFontMetricsPS::GetTextDimensions(const PRUnichar* aString, >+ PRInt32 aLength, >+ PRInt32 aAvailWidth, >+ PRInt32* aBreaks, >+ PRInt32 aNumBreaks, >+ nsTextDimensions& aDimensions, >+ PRInt32& aNumCharsFit, >+ nsTextDimensions& aLastWordDimensions, >+ PRInt32* aFontID) >+{ >+ NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions"); >+ return NS_ERROR_NOT_IMPLEMENTED; >+} >+ >+NS_IMETHODIMP >+nsFontMetricsPS :: GetTextDimensions(const char* aString, PRUint32 aLength, >+ nsTextDimensions& aDimensions) >+{ >+ GetStringWidth(aString, aDimensions.width, aLength); >+ GetMaxAscent(aDimensions.ascent); >+ GetMaxDescent(aDimensions.descent); >+ return NS_OK; >+} >+ >+NS_IMETHODIMP >+nsFontMetricsPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, >+ nsTextDimensions& aDimensions, PRInt32* aFontID) >+{ >+ GetStringWidth(aString, aDimensions.width, aLength); >+ //XXX temporary - bug 96609 >+ GetMaxAscent(aDimensions.ascent); >+ GetMaxDescent(aDimensions.descent); >+ return NS_OK; >+} >+ >+nsresult >+nsFontMetricsPS::GetBoundingMetrics(const char* aString, >+ PRUint32 aLength, >+ nsBoundingMetrics& aBoundingMetrics) >+{ >+ return NS_ERROR_NOT_IMPLEMENTED; >+} >+ >+nsresult >+nsFontMetricsPS::GetBoundingMetrics(const PRUnichar* aString, >+ PRUint32 aLength, >+ nsBoundingMetrics &aBoundingMetrics, >+ PRInt32 *aFontID) >+{ >+ return NS_ERROR_NOT_IMPLEMENTED; >+} >+ >+ > nsFontPS* > nsFontPS::FindFont(char aChar, const nsFont& aFont, > nsFontMetricsPS* aFontMetrics) >@@ -986,10 +1219,6 @@ nsFontPSXft::FindFont(PRUnichar aChar, c > result = FcPatternGetCharSet(set->fonts[i], FC_CHARSET, 0, &fc_charset); > if (result != FcResultMatch || fc_charset == nsnull) > continue; >- // increment reference count >- fc_charset = FcCharSetCopy(fc_charset); >- if (fc_charset == nsnull) >- continue; > > nsXftEntry *xftEntry = new nsXftEntry(set->fonts[i]); > if (!xftEntry) >@@ -997,7 +1226,7 @@ nsFontPSXft::FindFont(PRUnichar aChar, c > > fontps *fps = new fontps; > fps->entry = xftEntry; >- fps->charset = fc_charset; >+ fps->charset = FcCharSetCopy (fc_charset); > fps->fontps = nsnull; > fpi.fontps->AppendElement(fps); > } >@@ -1134,23 +1363,38 @@ nsFontPSXft::DrawString(nsRenderingConte > PRUint32 start = 0; > PRUint32 i; > >+ FT_Face face = getFTFace(); >+ if (!face) { >+ NS_WARNING("Failed to get FT Face in nsFontPSXft::DrawString\n"); >+ return 0; >+ } >+ >+ nsValueArray glyphs(PR_UINT16_MAX); >+ > // XXX : ignore surrogate pairs for now >- nsString *subSet = mPSFontGenerator->GetSubset(); > for (i = 0; i < aLength; ++i) { >- currSubFont = mPSFontGenerator->AddToSubset(aString[i]); >+ PRUint32 glyph = FT_Get_Char_Index(face, aString[i]); >+ currSubFont = mPSFontGenerator->AddToGlyphSubset(glyph); >+ >+ // Check if we need to render the current string > if (prevSubFont != currSubFont) { >- if (prevSubFont != -1) >- psObj->show(&aString[start], i - start, *subSet, prevSubFont); >+ if (prevSubFont != -1) { >+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont); >+ } > NS_ASSERTION(!mFontNameBase.IsEmpty(), > "font base name shouldn't be empty"); > psObj->setfont(mFontNameBase, mHeight, currSubFont); > prevSubFont = currSubFont; > start = i; >+ glyphs.Clear(); > } >+ >+ glyphs.AppendValue(glyph); > } > >- if (prevSubFont != -1) >- psObj->show(&aString[start], i - start, *subSet, prevSubFont); >+ if (prevSubFont != -1) { >+ psObj->show(&glyphs, mPSFontGenerator, prevSubFont); >+ } > > return GetWidth(aString, aLength); > } >@@ -2284,10 +2528,13 @@ nsFontPSFreeType::GetBoundingMetrics(con > // Implementation of nsPSFontGenerator > nsPSFontGenerator::nsPSFontGenerator() > { >+ mGlyphSubset = new nsValueArray(PR_UINT16_MAX, 40); > } > > nsPSFontGenerator::~nsPSFontGenerator() > { >+ if (mGlyphSubset) >+ delete mGlyphSubset; > } > > void nsPSFontGenerator::GeneratePSFont(FILE* aFile) >@@ -2295,24 +2542,29 @@ void nsPSFontGenerator::GeneratePSFont(F > NS_ERROR("should never call nsPSFontGenerator::GeneratePSFont"); > } > >-// Add a Unicode character to mSubset which will be divided into >-// multiple chunks (subfonts) of 255 (kSubFontSize) characters each. >-// Each chunk will be converted to a Type 1 font. Return the index of >-// a subfont (chunk) this character belongs to. >+// Add a glyph offset to mSubset which will be divided into multiple >+// chunks (subfonts) of 255 (kSubFontSize) glyphs each. Each chunk >+// will then be converted into a Type 1 font. Return the index of a >+// subfont (chunk) this glyph belongs to. > PRInt32 >-nsPSFontGenerator::AddToSubset(PRUnichar aChar) >+nsPSFontGenerator::AddToGlyphSubset(PRUint32 aGlyph) > { >- PRInt32 index = mSubset.FindChar(aChar); >- if (index == kNotFound) { >- mSubset.Append(aChar); >- index = mSubset.Length() - 1; >+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph); >+ if (index == NSVALUEARRAY_INVALID) { >+ mGlyphSubset->AppendValue(aGlyph); >+ index = mGlyphSubset->Count() - 1; > } >+ > return index / kSubFontSize; > } > >-nsString *nsPSFontGenerator::GetSubset() >+PRInt32 >+nsPSFontGenerator::InSubsetIndexOf(PRUint32 aGlyph) > { >- return &mSubset; >+ nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph); >+ if (index == NSVALUEARRAY_INVALID) >+ return 0; >+ return (index % kSubFontSize) + 1; > } > > #ifdef MOZ_ENABLE_XFT >@@ -2361,8 +2613,8 @@ void nsXftType1Generator::GeneratePSFont > } > > int wmode = 0; >- if (!mSubset.IsEmpty()) >- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile); >+ if (mGlyphSubset->Count()) >+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); > } > > #else >@@ -2410,8 +2662,8 @@ void nsFT2Type1Generator::GeneratePSFont > return; > > int wmode = 0; >- if (!mSubset.IsEmpty()) >- FT2SubsetToType1FontSet(face, mSubset, wmode, aFile); >+ if (mGlyphSubset->Count()) >+ FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile); > } > > #endif //MOZ_ENABLE_FREETYPE2 >--- mozilla/gfx/src/ps/nsType1.cpp.printing 2005-10-19 10:16:22.000000000 +0200 >+++ mozilla/gfx/src/ps/nsType1.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -73,8 +73,13 @@ > #include "nsIFreeType2.h" > #include "nsServiceManagerUtils.h" > #endif >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) >+#include FT_TYPE1_TABLES_H >+#endif > #include "nsPrintfCString.h" > #include "nsAutoBuffer.h" >+#include "nsValueArray.h" >+#include "nsVoidArray.h" > > #define HEXASCII_LINE_LEN 64 > >@@ -113,7 +118,7 @@ static void encryptAndHexOut(FILE *aFile > const char *aBuf, PRInt32 aLen = -1); > static void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey, > const char *aStr, PRUint32 aLen, >- PRUnichar aId); >+ const char *aGlyphName); > static void flattenName(nsCString& aString); > > /* thunk a short name for this function */ >@@ -202,19 +207,30 @@ Type1EncryptString(unsigned char *aInBuf > aOutBuf[i] = Type1Encrypt(aInBuf[i], &key); > } > >+static FT_UShort >+get_upm (FT_Face face) >+{ >+ FT_UShort upm = face->units_per_EM; >+ >+ if (!upm) >+ upm = 1000; // bitmap font or something >+ >+ return upm; >+} >+ > static PRBool > sideWidthAndBearing(const FT_Vector *aEndPt, FT2PT1_info *aFti) > { > int aw = 0; > int ah = 0; >- FT_UShort upm = aFti->face->units_per_EM; >+ FT_UShort upm = get_upm (aFti->face); > FT_GlyphSlot slot; > FT_Glyph glyph; > FT_BBox bbox; > > slot = aFti->face->glyph; > >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > FT_Error error = FT_Get_Glyph(slot, &glyph); > if (error) { > NS_ERROR("sideWidthAndBearing failed to get glyph"); >@@ -256,7 +272,7 @@ static int > moveto(nsFT_CONST FT_Vector *aEndPt, void *aClosure) > { > FT2PT1_info *fti = (FT2PT1_info *)aClosure; >- FT_UShort upm = fti->face->units_per_EM; >+ FT_UShort upm = get_upm (fti->face); > PRBool rslt; > > if (fti->elm_cnt == 0) { >@@ -293,7 +309,7 @@ static int > lineto(nsFT_CONST FT_Vector *aEndPt, void *aClosure) > { > FT2PT1_info *fti = (FT2PT1_info *)aClosure; >- FT_UShort upm = fti->face->units_per_EM; >+ FT_UShort upm = get_upm (fti->face); > > if (toCS(upm, aEndPt->x) == fti->cur_x) { > fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y); >@@ -320,7 +336,7 @@ conicto(nsFT_CONST FT_Vector *aControlPt > void *aClosure) > { > FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure; >- FT_UShort upm = ftinfo->face->units_per_EM; >+ FT_UShort upm = get_upm (ftinfo->face); > double ctl_x, ctl_y; > double cur_x, cur_y, x3, y3; > FT_Vector aControlPt1, aControlPt2; >@@ -353,7 +369,7 @@ cubicto(nsFT_CONST FT_Vector *aControlPt > nsFT_CONST FT_Vector *aEndPt, void *aClosure) > { > FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure; >- FT_UShort upm = ftinfo->face->units_per_EM; >+ FT_UShort upm = get_upm (ftinfo->face); > double cur_x, cur_y, x1, y1, x2, y2, x3, y3; > > cur_x = ftinfo->cur_x; >@@ -408,8 +424,55 @@ static FT_Outline_Funcs ft_outline_funcs > 0 > }; > >+ >+static int >+trace_bitmap_glyph (FT_GlyphSlot slot, FT2PT1_info *fti) >+{ >+ unsigned char *row, *byte_ptr, byte; >+ int rows, cols; >+ int x, y, bit_mask; >+ int upm, x_off, y_off, x_mult, y_mult; >+ >+ upm = get_upm (slot->face); >+ x_off = slot->bitmap_left; >+ y_off = slot->bitmap_top; >+ x_mult = upm / slot->face->size->metrics.x_ppem; >+ y_mult = upm / slot->face->size->metrics.y_ppem; >+ >+ switch (slot->bitmap.pixel_mode) { >+ case FT_PIXEL_MODE_MONO: >+ >+ for (y = 0, row = slot->bitmap.buffer, rows = slot->bitmap.rows; rows; row += slot->bitmap.pitch, rows--, y++) { >+ for (x = 0, byte_ptr = row, cols = (slot->bitmap.width + 7) / 8; cols; byte_ptr++, cols--) { >+ byte = *byte_ptr; >+ for (bit_mask = 128; bit_mask && x < slot->bitmap.width; bit_mask >>= 1, x++) { >+ if (byte & bit_mask) { >+ FT_Vector p; >+ p.x = x_mult * (x_off + x); >+ p.y = y_mult * (y_off - y); >+ moveto(&p, (void *) fti); >+ p.x += x_mult; >+ lineto(&p, (void *) fti); >+ p.y += y_mult; >+ lineto(&p, (void *) fti); >+ p.x -= x_mult; >+ lineto(&p, (void *) fti); >+ } >+ } >+ } >+ } >+ break; >+ >+ default: >+ return 1; >+ } >+ >+ return 0; >+} >+ >+ > FT_Error >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > FT2GlyphToType1CharString(FT_Face aFace, PRUint32 aGlyphID, > int aWmode, int aLenIV, unsigned char *aBuf) > #else >@@ -423,7 +486,7 @@ FT2GlyphToType1CharString(nsIFreeType2 * > unsigned char *start = aBuf; > FT2PT1_info fti; > >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > FT_Error error = FT_Load_Glyph(aFace, aGlyphID, flags); > if (error) { > NS_ERROR("failed to load aGlyphID"); >@@ -438,11 +501,6 @@ FT2GlyphToType1CharString(nsIFreeType2 * > #endif > slot = aFace->glyph; > >- if (slot->format != ft_glyph_format_outline) { >- NS_ERROR("aGlyphID is not an outline glyph"); >- return 1; >- } >- > #ifdef MOZ_ENABLE_FREETYPE2 > fti.ft2 = aFt2; > #endif >@@ -456,18 +514,27 @@ FT2GlyphToType1CharString(nsIFreeType2 * > for (j=0; j< aLenIV; j++) { > fti.len += ecsi(&fti.buf, 0); > } >-#ifdef MOZ_ENABLE_XFT >- if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) { >- NS_ERROR("error decomposing aGlyphID"); >- return 1; >- } >+ >+ if (slot->format == ft_glyph_format_outline) { >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) >+ if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti)) { >+ NS_ERROR("error decomposing aGlyphID"); >+ return 1; >+ } > #else >- rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti); >- if (NS_FAILED(rv)) { >- NS_ERROR("error decomposing aGlyphID"); >- return 1; >- } >+ rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti); >+ if (NS_FAILED(rv)) { >+ NS_ERROR("error decomposing aGlyphID"); >+ } > #endif >+ } else if (slot->format == ft_glyph_format_bitmap) { >+ /* ok, it's a bitmap glyph. trace it! */ >+ if (trace_bitmap_glyph (slot, &fti)) { >+ NS_ERROR("error tracing bitmap glyph"); >+ } >+ } else { >+ NS_ERROR("aGlyphID has unhandled format"); >+ } > > if (fti.elm_cnt) { > fti.len += csc(&fti.buf, T1_CLOSEPATH); >@@ -491,28 +558,52 @@ FT2GlyphToType1CharString(nsIFreeType2 * > } > > static PRBool >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > outputType1SubFont(FT_Face aFace, > #else > outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace, > #endif >- const nsAString &aCharIDs, const char *aFontName, >- int aWmode, int aLenIV, FILE *aFile); >+ nsValueArray *aGlyphs, >+ PRUint32 aOffset, PRUint32 aLen, >+ const char *aFontName, >+ int aWmode, int aLenIV, FILE *aFile); > > nsresult > FT2ToType1FontName(FT_Face aFace, int aWmode, nsCString& aFontName) > { >+ // only hash the first 10 000 bytes of the font >+ int size = aFace->stream->size; >+ size = size > 10000 ? 10000 : size; >+ >+ unsigned char *data; >+ if (aFace->stream->read) { >+ data = (unsigned char *) malloc (size); >+ aFace->stream->read (aFace->stream, 0, data, size); >+ } else { >+ data = aFace->stream->base; >+ } >+ >+ unsigned int data_hash = 0; >+ int i; >+ for (i = 0; i < size; i++) >+ data_hash = (data_hash << 5) - data_hash + data[size]; >+ >+ if (aFace->stream->read) >+ free (data); >+ > aFontName = aFace->family_name; > aFontName.AppendLiteral("."); > aFontName += aFace->style_name; >- aFontName += nsPrintfCString(".%ld.%d", aFace->face_index, aWmode ? 1 : 0); >+ aFontName += nsPrintfCString(".%ld.%d.%lx.%x", aFace->face_index, aWmode ? 1 : 0, >+ (long) aFace->stream->size, data_hash); > flattenName(aFontName); >+ > return NS_OK; > } > > // output a subsetted truetype font converted to multiple type 1 fonts > PRBool >-FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset, >+FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset, > int aWmode, FILE *aFile) > { > #ifdef MOZ_ENABLE_FREETYPE2 >@@ -527,32 +618,35 @@ FT2SubsetToType1FontSet(FT_Face aFace, c > nsCAutoString fontNameBase; > FT2ToType1FontName(aFace, aWmode, fontNameBase); > PRUint32 i = 0; >- for (; i <= aSubset.Length() / 255 ; i++) { >+ for (; i <= aGlyphSubset->Count() / 255 ; i++) { > nsCAutoString fontName(fontNameBase); > fontName.AppendLiteral(".Set"); > fontName.AppendInt(i); >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > outputType1SubFont(aFace, > #else > outputType1SubFont(ft2, aFace, > #endif >- Substring(aSubset, i * 255, PR_MIN(255, aSubset.Length() - i * 255)), >- fontName.get(), aWmode, 4, aFile); >+ aGlyphSubset, >+ (i * 255), PR_MIN(255, aGlyphSubset->Count() - i * 255), >+ fontName.get(), aWmode, 4, aFile); > } > return PR_TRUE; > } > > // output a type 1 font (with 255 characters or fewer) > static PRBool >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > outputType1SubFont(FT_Face aFace, > #else > outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace, > #endif >- const nsAString& aCharIDs, const char *aFontName, >- int aWmode, int aLenIV, FILE *aFile) >+ nsValueArray *aGlyphs, >+ PRUint32 aOffset, PRUint32 aLen, >+ const char *aFontName, >+ int aWmode, int aLenIV, FILE *aFile) > { >- FT_UShort upm = aFace->units_per_EM; >+ FT_UShort upm = get_upm (aFace); > > fprintf(aFile, "%%%%BeginResource: font %s\n" > "%%!PS-AdobeFont-1.0-3.0 %s 1.0\n" >@@ -573,9 +667,13 @@ outputType1SubFont(nsIFreeType2 *aFt2, F > toCS(upm, aFace->bbox.xMax), > toCS(upm, aFace->bbox.yMax)); > >- nsString charIDstr(aCharIDs); >- PRUint32 len = aCharIDs.Length(); >- >+ nsValueArray glyphs(PR_UINT16_MAX); >+ nsCStringArray glyphnames(PR_UINT16_MAX); >+ glyphs = *aGlyphs; >+ >+ PRUint32 len = aLen; >+ PRUint32 i; >+ > if (len < 10) { > // Add a small set of characters to the subset of the user > // defined font to produce to make sure the font ends up >@@ -584,25 +682,47 @@ outputType1SubFont(nsIFreeType2 *aFt2, F > // XXX : need to check if this is true of type 1 fonts as well. > // I suspect it's only the case of CID-keyed fonts (type 9) we used to > // generate. >- charIDstr.AppendLiteral("1234567890"); >+ for (i = 1; i <= 10; i++) { >+ glyphs.AppendValue(i); >+ } > len += 10; > } > >- const PRUnichar *charIDs = charIDstr.get(); >- >- PRUint32 i; >+ FT_Int has_glyph_name; >+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO) >+ has_glyph_name = FT_Has_PS_Glyph_Names(aFace); >+#else >+ has_glyph_name = aFt2->hasPSGlyphNames(aFace); >+#endif > > // construct an Encoding vector : the 0th element > // is /.notdef >- fputs("/Encoding [\n/.notdef\n", aFile); >- for (i = 0; i < len; ++i) { >- fprintf(aFile, "/uni%04X", charIDs[i]); >- if (i % 8 == 7) fputc('\n', aFile); >+ fputs("/Encoding [\n/.notdef", aFile); >+ for (i = aOffset; i < aOffset + aLen; ++i) { >+ nsCString name; >+ char buffer[256]; >+ >+ if (glyphs.ValueAt(i) == 0) { >+ name = "/.notdef"; >+ } else if (!has_glyph_name || >+#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO) >+ FT_Get_Glyph_Name(aFace, glyphs.ValueAt(i), buffer, 255) != FT_Err_Ok >+#else >+ NS_FAILED(aFt2->getGlyphName(aFace, glyphs.ValueAt(i), buffer, 255)) >+#endif >+ ) { >+ name = nsPrintfCString(256, "/idx%04X", glyphs.ValueAt(i)); >+ } else { >+ name = nsPrintfCString(256, "/%s", buffer); >+ } >+ glyphnames.AppendCString(name); >+ fprintf(aFile, name.get()); >+ if ((i-aOffset) % 8 == 6) fputc('\n', aFile); > } > >- for (i = len; i < 255; ++i) { >+ for (i = PR_MAX (0, 255 - int(aLen)); i; --i) { > fputs("/.notdef", aFile); >- if (i % 8 == 7) fputc('\n', aFile); >+ if (i % 8 == 1) fputc('\n', aFile); > } > fputs("] def\n", aFile); > >@@ -630,23 +750,21 @@ outputType1SubFont(nsIFreeType2 *aFt2, F > // get the maximum charstring length without actually filling up the buffer > PRInt32 charStringLen; > PRInt32 maxCharStringLen = >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, nsnull); > #else > FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, nsnull); > #endif > >- PRUint32 glyphID; >- >- for (i = 0; i < len; i++) { >-#ifdef MOZ_ENABLE_XFT >- glyphID = FT_Get_Char_Index(aFace, charIDs[i]); >+ for (i = aOffset; i < aOffset + aLen; i++) { >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > charStringLen = >- FT2GlyphToType1CharString(aFace, glyphID, aWmode, aLenIV, nsnull); >+ FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, aLenIV, >+ nsnull); > #else >- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID); > charStringLen = >- FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, aLenIV, nsnull); >+ FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), aWmode, aLenIV, >+ nsnull); > #endif > > if (charStringLen > maxCharStringLen) >@@ -666,7 +784,7 @@ outputType1SubFont(nsIFreeType2 *aFt2, F > len + 1).get()); > > // output the notdef glyph >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > charStringLen = FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, > charString.get()); > #else >@@ -676,22 +794,20 @@ outputType1SubFont(nsIFreeType2 *aFt2, F > > // enclose charString with "/.notdef RD ..... ND" > charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()), >- charStringLen, 0); >+ charStringLen, "/.notdef"); > > > // output the charstrings for each glyph in this sub font >- for (i = 0; i < len; i++) { >-#ifdef MOZ_ENABLE_XFT >- glyphID = FT_Get_Char_Index(aFace, charIDs[i]); >- charStringLen = FT2GlyphToType1CharString(aFace, glyphID, aWmode, >+ for (i = aOffset; i < aOffset + aLen; i++) { >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) >+ charStringLen = FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, > aLenIV, charString.get()); > #else >- aFt2->GetCharIndex(aFace, charIDs[i], &glyphID); >- charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, >- aLenIV, charString.get()); >+ charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), >+ aWmode, aLenIV, charString.get()); > #endif > charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()), >- charStringLen, charIDs[i]); >+ charStringLen, glyphnames.CStringAt(i - aOffset)->get()); > } > > // wrap up the encrypted part of the font definition >@@ -753,15 +869,12 @@ void encryptAndHexOut(FILE *aFile, PRUin > > /* static */ > void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey, >- const char *aStr, PRUint32 aLen, PRUnichar aId) >+ const char *aStr, PRUint32 aLen, const char *aGlyphName) > { > // use a local buffer instead of nsPrintfCString to avoid alloc. > char buf[30]; > int oLen; >- if (aId == 0) >- oLen = PR_snprintf(buf, 30, "/.notdef %d RD ", aLen); >- else >- oLen = PR_snprintf(buf, 30, "/uni%04X %d RD ", aId, aLen); >+ oLen = PR_snprintf(buf, 30, "%s %d RD ", aGlyphName, aLen); > > if (oLen >= 30) { > NS_WARNING("buffer size exceeded. charstring will be truncated"); >--- mozilla/gfx/src/ps/Makefile.in.printing 2005-03-04 08:39:27.000000000 +0100 >+++ mozilla/gfx/src/ps/Makefile.in 2007-07-03 15:40:51.000000000 +0200 >@@ -98,13 +98,25 @@ EXTRA_DSO_LDOPTS = \ > $(MOZ_UNICHARUTIL_LIBS) \ > $(NULL) > >+ifdef MOZ_ENABLE_PANGO >+CPPSRCS += \ >+ nsFontMetricsPango.cpp \ >+ mozilla-decoder.cpp >+CSRCS += \ >+ pango-renderer.c >+EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) >+CXXFLAGS += $(MOZ_PANGO_CFLAGS) >+CFLAGS += $(MOZ_PANGO_CFLAGS) >+DEFINES += -DPSPANGO >+endif >+ > ifdef MOZ_ENABLE_XFT > EXTRA_DSO_LDOPTS += \ > $(MOZ_XFT_LIBS) \ > $(NULL) > endif > >-ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)) >+ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)$(MOZ_ENABLE_PANGO)) > CPPSRCS += \ > nsType1.cpp \ > $(NULL) >--- mozilla/gfx/src/ps/nsDeviceContextPS.cpp.printing 2005-05-21 17:33:08.000000000 +0200 >+++ mozilla/gfx/src/ps/nsDeviceContextPS.cpp 2007-07-03 15:40:51.000000000 +0200 >@@ -58,12 +58,15 @@ > #include "nsIPref.h" > #include "nsString.h" > #include "nsFontMetricsPS.h" >+#ifdef MOZ_ENABLE_PANGO >+#include "nsFontMetricsPango.h" >+#endif > #include "nsPostScriptObj.h" > #include "nspr.h" > #include "nsILanguageAtomService.h" > #include "nsPrintJobPS.h" > #include "nsPrintJobFactoryPS.h" >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > #include "nsType1.h" > #endif > >@@ -223,7 +226,7 @@ nsDeviceContextPS::InitDeviceContextPS(n > > nsresult rv; > nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv)); >-#ifdef MOZ_ENABLE_XFT >+#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > if (NS_SUCCEEDED(rv)) { > rv = pref->GetBoolPref("font.FreeType2.printing", &mFTPEnable); > if (NS_FAILED(rv)) >@@ -469,7 +472,7 @@ NS_IMETHODIMP nsDeviceContextPS::EndDocu > NS_ASSERTION(submitFP, "No print job submission handle"); > > // Start writing the print job to the job handler >-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) >+#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO) > mPSObj->write_prolog(submitFP, mFTPEnable); > #else > mPSObj->write_prolog(submitFP); >@@ -550,15 +553,52 @@ public: > virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** aResult); > }; > >+#if defined(MOZ_ENABLE_PANGO) >+PRBool >+NS_IsPangoEnabled(void) >+{ >+ static PRBool beenHere; >+ static PRBool pangoEnabled; >+ >+ if (!beenHere) { >+ beenHere = PR_TRUE; >+ >+ char *val = PR_GetEnv("MOZ_DISABLE_PANGO"); >+ pangoEnabled = !(val); >+ >+ if (pangoEnabled) { >+ nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID); >+ if (prefService) >+ prefService->SetDefaultCharPref("general.useragent.extra.pango", >+ "pango-text"); >+ } >+ } >+ >+ return pangoEnabled; >+} >+#endif > > nsresult nsFontCachePS::CreateFontMetricsInstance(nsIFontMetrics** aResult) > { > NS_PRECONDITION(aResult, "null out param"); >- nsIFontMetrics *fm = new nsFontMetricsPS(); >- if (!fm) >- return NS_ERROR_OUT_OF_MEMORY; >- NS_ADDREF(fm); >- *aResult = fm; >+#ifdef MOZ_ENABLE_PANGO >+ if (NS_IsPangoEnabled()) >+ { >+ nsIFontMetrics *fm = new nsFontMetricsPSPango(); >+ if (!fm) >+ return NS_ERROR_OUT_OF_MEMORY; >+ NS_ADDREF(fm); >+ *aResult = fm; >+ } >+ else >+#endif >+ { >+ nsIFontMetrics *fm = new nsFontMetricsPS(); >+ if (!fm) >+ return NS_ERROR_OUT_OF_MEMORY; >+ NS_ADDREF(fm); >+ *aResult = fm; >+ } > return NS_OK; > } > >--- mozilla/gfx/src/ps/nsType1.h.printing 2005-03-04 08:39:27.000000000 +0100 >+++ mozilla/gfx/src/ps/nsType1.h 2007-07-03 15:40:51.000000000 +0200 >@@ -122,8 +122,9 @@ FT_Error FT2GlyphToType1CharString(nsIFr > > class nsString; > class nsCString; >+class nsValueArray; > >-PRBool FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset, >+PRBool FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset, > int aWmode, FILE *aFile); > nsresult FT2ToType1FontName(FT_Face aFace, int aWmode, > nsCString& aFontName);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 129207
: 158506