Start fleshing out builtin font functions
This commit is contained in:
parent
343a0e4e74
commit
903648437c
|
@ -51,7 +51,6 @@ HBSOURCES = \
|
||||||
hb-shaper-impl-private.hh \
|
hb-shaper-impl-private.hh \
|
||||||
hb-shaper-private.hh \
|
hb-shaper-private.hh \
|
||||||
hb-shaper.cc \
|
hb-shaper.cc \
|
||||||
hb-tt-font.cc \
|
|
||||||
hb-unicode-private.hh \
|
hb-unicode-private.hh \
|
||||||
hb-unicode.cc \
|
hb-unicode.cc \
|
||||||
hb-utf-private.hh \
|
hb-utf-private.hh \
|
||||||
|
@ -76,6 +75,7 @@ HBNODISTHEADERS = \
|
||||||
|
|
||||||
if HAVE_OT
|
if HAVE_OT
|
||||||
HBSOURCES += \
|
HBSOURCES += \
|
||||||
|
hb-ot-font.cc \
|
||||||
hb-ot-layout.cc \
|
hb-ot-layout.cc \
|
||||||
hb-ot-layout-common-private.hh \
|
hb-ot-layout-common-private.hh \
|
||||||
hb-ot-layout-gdef-table.hh \
|
hb-ot-layout-gdef-table.hh \
|
||||||
|
@ -112,6 +112,7 @@ HBSOURCES += \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
HBHEADERS += \
|
HBHEADERS += \
|
||||||
hb-ot.h \
|
hb-ot.h \
|
||||||
|
hb-ot-font.h \
|
||||||
hb-ot-layout.h \
|
hb-ot-layout.h \
|
||||||
hb-ot-shape.h \
|
hb-ot-shape.h \
|
||||||
hb-ot-tag.h \
|
hb-ot-tag.h \
|
||||||
|
|
|
@ -340,7 +340,7 @@ hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||||
void *user_data HB_UNUSED)
|
void *user_data HB_UNUSED)
|
||||||
{
|
{
|
||||||
#if GLIB_CHECK_VERSION(2,29,12)
|
#if GLIB_CHECK_VERSION(2,29,12)
|
||||||
return g_unichar_fully_decompose (u, TRUE, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
|
return g_unichar_fully_decompose (u, true, decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the user doesn't have GLib >= 2.29.12 we have to perform
|
/* If the user doesn't have GLib >= 2.29.12 we have to perform
|
||||||
|
|
|
@ -323,7 +323,7 @@ hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
||||||
|
|
||||||
/* Copy @u into a UTF-16 array to be passed to ICU. */
|
/* Copy @u into a UTF-16 array to be passed to ICU. */
|
||||||
len = 0;
|
len = 0;
|
||||||
err = FALSE;
|
err = false;
|
||||||
U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
|
U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err);
|
||||||
if (err)
|
if (err)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011,2014 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod, Roozbeh Pournader
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hb-private.hh"
|
||||||
|
|
||||||
|
#include "hb-ot.h"
|
||||||
|
|
||||||
|
#include "hb-font-private.hh"
|
||||||
|
|
||||||
|
#include "hb-ot-hhea-table.hh"
|
||||||
|
#include "hb-ot-hmtx-table.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct hb_ot_font_t
|
||||||
|
{
|
||||||
|
unsigned int num_glyphs;
|
||||||
|
unsigned int num_hmetrics;
|
||||||
|
const OT::hmtx *hmtx;
|
||||||
|
hb_blob_t *hmtx_blob;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static hb_ot_font_t *
|
||||||
|
_hb_ot_font_create (hb_font_t *font)
|
||||||
|
{
|
||||||
|
hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
|
||||||
|
|
||||||
|
if (unlikely (!ot_font))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ot_font->num_glyphs = font->face->get_num_glyphs ();
|
||||||
|
|
||||||
|
{
|
||||||
|
hb_blob_t *hhea_blob = OT::Sanitizer<OT::hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
||||||
|
const OT::hhea *hhea = OT::Sanitizer<OT::hhea>::lock_instance (hhea_blob);
|
||||||
|
ot_font->num_hmetrics = hhea->numberOfHMetrics;
|
||||||
|
hb_blob_destroy (hhea_blob);
|
||||||
|
}
|
||||||
|
ot_font->hmtx_blob = OT::Sanitizer<OT::hmtx>::sanitize (font->face->reference_table (HB_OT_TAG_hmtx));
|
||||||
|
if (unlikely (!ot_font->num_hmetrics ||
|
||||||
|
2 * (ot_font->num_hmetrics + ot_font->num_glyphs) < hb_blob_get_length (ot_font->hmtx_blob)))
|
||||||
|
{
|
||||||
|
hb_blob_destroy (ot_font->hmtx_blob);
|
||||||
|
free (ot_font);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ot_font->hmtx = OT::Sanitizer<OT::hmtx>::lock_instance (ot_font->hmtx_blob);
|
||||||
|
|
||||||
|
return ot_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_ot_font_destroy (hb_ot_font_t *ot_font)
|
||||||
|
{
|
||||||
|
hb_blob_destroy (ot_font->hmtx_blob);
|
||||||
|
|
||||||
|
free (ot_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t unicode,
|
||||||
|
hb_codepoint_t variation_selector,
|
||||||
|
hb_codepoint_t *glyph,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
FT_Face ft_face = (FT_Face) font_data;
|
||||||
|
|
||||||
|
#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
|
||||||
|
if (unlikely (variation_selector)) {
|
||||||
|
*glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
|
||||||
|
return *glyph != 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*glyph = FT_Get_Char_Index (ft_face, unicode);
|
||||||
|
return *glyph != 0;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_position_t
|
||||||
|
hb_ot_get_glyph_h_advance (hb_font_t *font,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||||
|
|
||||||
|
if (unlikely (glyph >= ot_font->num_glyphs))
|
||||||
|
return 0; /* Maybe better to return notdef's advance instead? */
|
||||||
|
|
||||||
|
if (glyph >= ot_font->num_hmetrics)
|
||||||
|
glyph = ot_font->num_hmetrics - 1;
|
||||||
|
|
||||||
|
return font->em_scale_x (ot_font->hmtx->longHorMetric[glyph].advanceWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_position_t
|
||||||
|
hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data HB_UNUSED,
|
||||||
|
hb_codepoint_t glyph HB_UNUSED,
|
||||||
|
hb_position_t *x HB_UNUSED,
|
||||||
|
hb_position_t *y HB_UNUSED,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* We always work in the horizontal coordinates. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_position_t *x,
|
||||||
|
hb_position_t *y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_position_t
|
||||||
|
hb_ot_get_glyph_h_kerning (hb_font_t *font,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t left_glyph,
|
||||||
|
hb_codepoint_t right_glyph,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_position_t
|
||||||
|
hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data HB_UNUSED,
|
||||||
|
hb_codepoint_t top_glyph HB_UNUSED,
|
||||||
|
hb_codepoint_t bottom_glyph HB_UNUSED,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_glyph_extents_t *extents,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
unsigned int point_index,
|
||||||
|
hb_position_t *x,
|
||||||
|
hb_position_t *y,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
char *name, unsigned int size,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
|
||||||
|
void *font_data,
|
||||||
|
const char *name, int len, /* -1 means nul-terminated */
|
||||||
|
hb_codepoint_t *glyph,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static hb_font_funcs_t *
|
||||||
|
_hb_ot_get_font_funcs (void)
|
||||||
|
{
|
||||||
|
static const hb_font_funcs_t ot_ffuncs = {
|
||||||
|
HB_OBJECT_HEADER_STATIC,
|
||||||
|
|
||||||
|
true, /* immutable */
|
||||||
|
|
||||||
|
{
|
||||||
|
#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
|
||||||
|
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
|
||||||
|
#undef HB_FONT_FUNC_IMPLEMENT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_font_set_funcs (hb_font_t *font)
|
||||||
|
{
|
||||||
|
hb_ot_font_t *ot_font = _hb_ot_font_create (font);
|
||||||
|
if (unlikely (!ot_font))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hb_font_set_funcs (font,
|
||||||
|
_hb_ot_get_font_funcs (),
|
||||||
|
ot_font,
|
||||||
|
(hb_destroy_func_t) _hb_ot_font_destroy);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2011 Google, Inc.
|
* Copyright © 2014 Google, Inc.
|
||||||
*
|
*
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
|
@ -21,57 +21,21 @@
|
||||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* Google Author(s): Behdad Esfahbod
|
* Google Author(s): Behdad Esfahbod, Roozbeh Pournader
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hb-font-private.hh" /* Shall be first since may include windows.h */
|
#ifndef HB_OT_FONT_H
|
||||||
|
#define HB_OT_FONT_H
|
||||||
|
|
||||||
#include "hb-open-type-private.hh"
|
#include "hb.h"
|
||||||
|
|
||||||
#include "hb-ot-hhea-table.hh"
|
HB_BEGIN_DECLS
|
||||||
#include "hb-ot-hmtx-table.hh"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
#if 0
|
hb_ot_font_set_funcs (hb_font_t *font);
|
||||||
struct hb_tt_font_t
|
|
||||||
{
|
|
||||||
const struct hhea *hhea;
|
|
||||||
hb_blob_t *hhea_blob;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static hb_tt_font_t *
|
HB_END_DECLS
|
||||||
_hb_tt_font_create (hb_font_t *font)
|
|
||||||
{
|
|
||||||
/* TODO Remove this object altogether */
|
|
||||||
hb_tt_font_t *tt = (hb_tt_font_t *) calloc (1, sizeof (hb_tt_font_t));
|
|
||||||
|
|
||||||
tt->hhea_blob = Sanitizer<hhea>::sanitize (font->face->reference_table (HB_OT_TAG_hhea));
|
#endif /* HB_OT_FONT_H */
|
||||||
tt->hhea = Sanitizer<hhea>::lock_instance (tt->hhea_blob);
|
|
||||||
|
|
||||||
return tt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_hb_tt_font_destroy (hb_tt_font_t *tt)
|
|
||||||
{
|
|
||||||
hb_blob_destroy (tt->hhea_blob);
|
|
||||||
|
|
||||||
free (tt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const hhea&
|
|
||||||
_get_hhea (hb_face_t *face)
|
|
||||||
{
|
|
||||||
return likely (face->tt && face->tt->hhea) ? *face->tt->hhea : Null(hhea);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* hb_tt_font_funcs_t
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -49,7 +49,7 @@ struct hhea
|
||||||
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
|
return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
FixedVersion version; /* 0x00010000 for version 1.0. */
|
FixedVersion version; /* 0x00010000 for version 1.0. */
|
||||||
FWORD ascender; /* Typographic ascent. <a
|
FWORD ascender; /* Typographic ascent. <a
|
||||||
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
|
* href="http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html">
|
||||||
|
|
|
@ -59,7 +59,7 @@ struct hmtx
|
||||||
return TRACE_RETURN (true);
|
return TRACE_RETURN (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
|
LongHorMetric longHorMetric[VAR]; /* Paired advance width and left side
|
||||||
* bearing values for each glyph. The
|
* bearing values for each glyph. The
|
||||||
* value numOfHMetrics comes from
|
* value numOfHMetrics comes from
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "hb.h"
|
#include "hb.h"
|
||||||
|
|
||||||
|
#include "hb-ot-font.h"
|
||||||
#include "hb-ot-layout.h"
|
#include "hb-ot-layout.h"
|
||||||
#include "hb-ot-tag.h"
|
#include "hb-ot-tag.h"
|
||||||
#include "hb-ot-shape.h"
|
#include "hb-ot-shape.h"
|
||||||
|
|
|
@ -24,8 +24,8 @@ LDADD = \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
if HAVE_GLIB
|
if HAVE_GLIB
|
||||||
if HAVE_FREETYPE
|
|
||||||
|
|
||||||
|
if HAVE_FREETYPE
|
||||||
if HAVE_CAIRO_FT
|
if HAVE_CAIRO_FT
|
||||||
hb_view_SOURCES = \
|
hb_view_SOURCES = \
|
||||||
hb-view.cc \
|
hb-view.cc \
|
||||||
|
@ -49,6 +49,7 @@ hb_view_LDADD = \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
bin_PROGRAMS += hb-view
|
bin_PROGRAMS += hb-view
|
||||||
endif # HAVE_CAIRO_FT
|
endif # HAVE_CAIRO_FT
|
||||||
|
endif # HAVE_FREETYPE
|
||||||
|
|
||||||
hb_shape_SOURCES = \
|
hb_shape_SOURCES = \
|
||||||
hb-shape.cc \
|
hb-shape.cc \
|
||||||
|
@ -69,7 +70,6 @@ hb_ot_shape_closure_SOURCES = \
|
||||||
bin_PROGRAMS += hb-ot-shape-closure
|
bin_PROGRAMS += hb-ot-shape-closure
|
||||||
endif # HAVE_OT
|
endif # HAVE_OT
|
||||||
|
|
||||||
endif # HAVE_FREETYPE
|
|
||||||
endif # HAVE_GLIB
|
endif # HAVE_GLIB
|
||||||
|
|
||||||
-include $(top_srcdir)/git.mk
|
-include $(top_srcdir)/git.mk
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
#ifdef HAVE_FREETYPE
|
#ifdef HAVE_FREETYPE
|
||||||
#include <hb-ft.h>
|
#include <hb-ft.h>
|
||||||
|
#else
|
||||||
|
#include <hb-ot-font.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -486,6 +488,8 @@ font_options_t::get_font (void) const
|
||||||
|
|
||||||
#ifdef HAVE_FREETYPE
|
#ifdef HAVE_FREETYPE
|
||||||
hb_ft_font_set_funcs (font);
|
hb_ft_font_set_funcs (font);
|
||||||
|
#else
|
||||||
|
hb_ot_font_set_funcs (font);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
|
|
Loading…
Reference in New Issue