mirror of https://github.com/GNOME/gimp.git
258 lines
5.8 KiB
C
258 lines
5.8 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* GimpText
|
|
* Copyright (C) 2003 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib-object.h>
|
|
|
|
#include <pango/pangoft2.h>
|
|
|
|
#include <ft2build.h>
|
|
#include FT_GLYPH_H
|
|
#include FT_OUTLINE_H
|
|
|
|
#include "text/text-types.h"
|
|
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "vectors/gimpbezierstroke.h"
|
|
#include "vectors/gimpvectors.h"
|
|
#include "vectors/gimpanchor.h"
|
|
|
|
#include "gimptext.h"
|
|
#include "gimptext-private.h"
|
|
#include "gimptext-vectors.h"
|
|
#include "gimptextlayout.h"
|
|
#include "gimptextlayout-render.h"
|
|
|
|
|
|
/* for compatibility with older freetype versions */
|
|
#ifndef FT_GLYPH_FORMAT_OUTLINE
|
|
#define FT_GLYPH_FORMAT_OUTLINE ft_glyph_format_outline
|
|
#endif
|
|
|
|
typedef struct _RenderContext RenderContext;
|
|
|
|
struct _RenderContext
|
|
{
|
|
GimpVectors *vectors;
|
|
GimpStroke *stroke;
|
|
GimpAnchor *anchor;
|
|
gdouble offset_x;
|
|
gdouble offset_y;
|
|
};
|
|
|
|
|
|
static void gimp_text_render_vectors (PangoFont *font,
|
|
PangoGlyph glyph,
|
|
FT_Int32 flags,
|
|
FT_Matrix *matrix,
|
|
gint x,
|
|
gint y,
|
|
RenderContext *context);
|
|
|
|
|
|
GimpVectors *
|
|
gimp_text_vectors_new (GimpImage *image,
|
|
GimpText *text)
|
|
{
|
|
GimpVectors *vectors;
|
|
GimpTextLayout *layout;
|
|
RenderContext context = { 0, };
|
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
|
g_return_val_if_fail (GIMP_IS_TEXT (text), NULL);
|
|
|
|
vectors = gimp_vectors_new (image, NULL);
|
|
|
|
if (text->text)
|
|
{
|
|
gimp_object_set_name_safe (GIMP_OBJECT (vectors), text->text);
|
|
|
|
layout = gimp_text_layout_new (text, image);
|
|
|
|
context.vectors = vectors;
|
|
|
|
gimp_text_layout_render (layout,
|
|
(GimpTextRenderFunc) gimp_text_render_vectors,
|
|
&context);
|
|
|
|
g_object_unref (layout);
|
|
|
|
if (context.stroke)
|
|
gimp_stroke_close (context.stroke);
|
|
}
|
|
|
|
return vectors;
|
|
}
|
|
|
|
|
|
static inline void
|
|
gimp_text_vector_coords (RenderContext *context,
|
|
const FT_Vector *vector,
|
|
GimpCoords *coords)
|
|
{
|
|
coords->x = context->offset_x + (gdouble) vector->x / 64.0;
|
|
coords->y = context->offset_y - (gdouble) vector->y / 64.0;
|
|
coords->pressure = 1.0;
|
|
coords->xtilt = 0.5;
|
|
coords->ytilt = 0.5;
|
|
coords->wheel = 0.5;
|
|
}
|
|
|
|
static gint
|
|
moveto (FT_Vector *to,
|
|
gpointer data)
|
|
{
|
|
RenderContext *context = (RenderContext *) data;
|
|
GimpCoords start;
|
|
|
|
#if GIMP_TEXT_DEBUG
|
|
g_printerr ("moveto %f, %f\n", to->x / 64.0, to->y / 64.0);
|
|
#endif
|
|
|
|
gimp_text_vector_coords (context, to, &start);
|
|
|
|
if (context->stroke)
|
|
gimp_stroke_close (context->stroke);
|
|
|
|
context->stroke = gimp_bezier_stroke_new_moveto (&start);
|
|
|
|
gimp_vectors_stroke_add (context->vectors, context->stroke);
|
|
g_object_unref (context->stroke);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
lineto (FT_Vector *to,
|
|
gpointer data)
|
|
{
|
|
RenderContext *context = (RenderContext *) data;
|
|
GimpCoords end;
|
|
|
|
#if GIMP_TEXT_DEBUG
|
|
g_printerr ("lineto %f, %f\n", to->x / 64.0, to->y / 64.0);
|
|
#endif
|
|
|
|
if (! context->stroke)
|
|
return 0;
|
|
|
|
gimp_text_vector_coords (context, to, &end);
|
|
|
|
gimp_bezier_stroke_lineto (context->stroke, &end);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
conicto (FT_Vector *ftcontrol,
|
|
FT_Vector *to,
|
|
gpointer data)
|
|
{
|
|
RenderContext *context = (RenderContext *) data;
|
|
GimpCoords control;
|
|
GimpCoords end;
|
|
|
|
#if GIMP_TEXT_DEBUG
|
|
g_printerr ("conicto %f, %f\n", to->x / 64.0, to->y / 64.0);
|
|
#endif
|
|
|
|
if (! context->stroke)
|
|
return 0;
|
|
|
|
gimp_text_vector_coords (context, ftcontrol, &control);
|
|
gimp_text_vector_coords (context, to, &end);
|
|
|
|
gimp_bezier_stroke_conicto (context->stroke, &control, &end);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
cubicto (FT_Vector *ftcontrol1,
|
|
FT_Vector *ftcontrol2,
|
|
FT_Vector *to,
|
|
gpointer data)
|
|
{
|
|
RenderContext *context = (RenderContext *) data;
|
|
GimpCoords control1;
|
|
GimpCoords control2;
|
|
GimpCoords end;
|
|
|
|
#if GIMP_TEXT_DEBUG
|
|
g_printerr ("cubicto %f, %f\n", to->x / 64.0, to->y / 64.0);
|
|
#endif
|
|
|
|
if (! context->stroke)
|
|
return 0;
|
|
|
|
gimp_text_vector_coords (context, ftcontrol1, &control1);
|
|
gimp_text_vector_coords (context, ftcontrol2, &control2);
|
|
gimp_text_vector_coords (context, to, &end);
|
|
|
|
gimp_bezier_stroke_cubicto (context->stroke, &control1, &control2, &end);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
gimp_text_render_vectors (PangoFont *font,
|
|
PangoGlyph pango_glyph,
|
|
FT_Int32 flags,
|
|
FT_Matrix *trafo,
|
|
gint x,
|
|
gint y,
|
|
RenderContext *context)
|
|
{
|
|
const FT_Outline_Funcs outline_funcs =
|
|
{
|
|
moveto,
|
|
lineto,
|
|
conicto,
|
|
cubicto,
|
|
0,
|
|
0
|
|
};
|
|
|
|
FT_Face face;
|
|
FT_Glyph glyph;
|
|
|
|
face = pango_ft2_font_get_face (font);
|
|
|
|
FT_Load_Glyph (face, (FT_UInt) pango_glyph, flags);
|
|
|
|
FT_Get_Glyph (face->glyph, &glyph);
|
|
|
|
if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
{
|
|
FT_OutlineGlyph outline_glyph = (FT_OutlineGlyph) glyph;
|
|
|
|
context->offset_x = (gdouble) x / PANGO_SCALE;
|
|
context->offset_y = (gdouble) y / PANGO_SCALE;
|
|
|
|
FT_Outline_Decompose (&outline_glyph->outline, &outline_funcs, context);
|
|
}
|
|
|
|
FT_Done_Glyph (glyph);
|
|
}
|