Beispiel #1
0
void cdSimTextFT(cdCtxCanvas* ctxcanvas, int x, int y, const char* s, int len)
{
  cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
  cdSimulation* simulation = canvas->simulation;
  FT_Face       face;
  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;
  int i = 0;

  if (!simulation->tt_text->face)
    return;

  face = simulation->tt_text->face;
  slot = face->glyph;

  /* the pen position is in cartesian space coordinates */
  if (simulation->canvas->invert_yaxis)
    y = _cdInvertYAxis(canvas, y);   /* y is already inverted, invert back to cartesian space */

  /* move the reference point to the baseline-left */
  simGetPenPos(simulation->canvas, x, y, s, len, &matrix, &pen);

  while(i<len)
  {
    /* set transformation */
    FT_Set_Transform(face, &matrix, &pen);

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char(face, (unsigned char)s[i], FT_LOAD_RENDER);
    if (error) {i++; continue;}  /* ignore errors */

    x = slot->bitmap_left;
    y = slot->bitmap_top-slot->bitmap.rows; /* CD image reference point is at bottom-left */

    if (canvas->invert_yaxis)
      y = _cdInvertYAxis(canvas, y);

    /* now, draw to our target surface (convert position) */
    simDrawTextBitmap(simulation, &slot->bitmap, x, y);

    /* increment pen position */
    pen.x += slot->advance.x;
    pen.y += slot->advance.y;

    i++;
  }
}
Beispiel #2
0
font_face_set::dimension_t font_face_set::character_dimensions(const unsigned c)
{
    std::map<unsigned, dimension_t>::const_iterator itr;
    itr = dimension_cache_.find(c);
    if (itr != dimension_cache_.end()) {
        return itr->second;
    }

    FT_Matrix matrix;
    FT_Vector pen;
    FT_Error  error;

    pen.x = 0;
    pen.y = 0;

    FT_BBox glyph_bbox;
    FT_Glyph image;

    glyph_ptr glyph = get_glyph(c);
    FT_Face face = glyph->get_face()->get_face();

    matrix.xx = (FT_Fixed)( 1 * 0x10000L );
    matrix.xy = (FT_Fixed)( 0 * 0x10000L );
    matrix.yx = (FT_Fixed)( 0 * 0x10000L );
    matrix.yy = (FT_Fixed)( 1 * 0x10000L );

    FT_Set_Transform(face, &matrix, &pen);

    error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
    if ( error )
        return dimension_t(0, 0, 0);

    error = FT_Get_Glyph(face->glyph, &image);
    if ( error )
        return dimension_t(0, 0, 0);

    FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
    FT_Done_Glyph(image);

    unsigned tempx = face->glyph->advance.x >> 6;

    //std::clog << "glyph: " << glyph_index << " x: " << tempx << " y: " << tempy << std::endl;
    dimension_t dim(tempx, glyph_bbox.yMax, glyph_bbox.yMin);
    //dimension_cache_[c] = dim; would need an default constructor for dimension_t
    dimension_cache_.insert(std::pair<unsigned, dimension_t>(c, dim));
    return dim;
}
Beispiel #3
0
char_info font_face_set::character_dimensions(const unsigned c)
{
    //Check if char is already in cache
    std::map<unsigned, char_info>::const_iterator itr;
    itr = dimension_cache_.find(c);
    if (itr != dimension_cache_.end()) {
        return itr->second;
    }

    FT_Matrix matrix;
    FT_Vector pen;
    FT_Error  error;

    pen.x = 0;
    pen.y = 0;

    FT_BBox glyph_bbox;
    FT_Glyph image;

    glyph_ptr glyph = get_glyph(c);
    FT_Face face = glyph->get_face()->get_face();

    matrix.xx = (FT_Fixed)( 1 * 0x10000L );
    matrix.xy = (FT_Fixed)( 0 * 0x10000L );
    matrix.yx = (FT_Fixed)( 0 * 0x10000L );
    matrix.yy = (FT_Fixed)( 1 * 0x10000L );

    FT_Set_Transform(face, &matrix, &pen);

    error = FT_Load_Glyph (face, glyph->get_index(), FT_LOAD_NO_HINTING);
    if ( error )
        return char_info();

    error = FT_Get_Glyph(face->glyph, &image);
    if ( error )
        return char_info();

    FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
    FT_Done_Glyph(image);

    unsigned tempx = face->glyph->advance.x >> 6;

    char_info dim(c, tempx, glyph_bbox.yMax, glyph_bbox.yMin, face->size->metrics.height/64.0 /* >> 6 */);
    dimension_cache_.insert(std::pair<unsigned, char_info>(c, dim));
    return dim;
}
static int setupFTContext(JNIEnv *env,
                          jobject font2D,
                          FTScalerInfo *scalerInfo,
                          FTScalerContext *context) {
    int errCode = 0;

    scalerInfo->env = env;
    scalerInfo->font2D = font2D;

    if (context != NULL) {
        FT_Set_Transform(scalerInfo->face, &context->transform, NULL);

        errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);

        if (errCode == 0) {
            errCode = FT_Activate_Size(scalerInfo->face->size);
        }
    }

    return errCode;
}
Beispiel #5
0
_JATTA_EXPORT Jatta::Glyph::Glyph(::FT_Face face, UInt32 utf8Character)
{
    FT_Matrix matrix;
    matrix.xx = (FT_Fixed)(1 * 0x10000L);
    matrix.xy = (FT_Fixed)(0 * 0x10000L);
    matrix.yx = (FT_Fixed)(0 * 0x10000L);
    matrix.yy = (FT_Fixed)(1 * 0x10000L);
    FT_Vector pen;
    pen.x = 0;
    pen.y = 0;

    if (face->style_flags & FontStyles::OBLIQUE)
    {
        double pi = 3.1415926535;;
        double rads = pi * 0.0f / 180.0;
        double skew = pi * 35.0f/ 180.0;

        // set up transform (a rotation here)
        matrix.xx = (FT_Fixed)( Math::Cos(rads)*0x10000L);
        matrix.xy = (FT_Fixed)( Math::Sin(rads + skew)*0x10000L);
        matrix.yx = (FT_Fixed)( Math::Sin(rads)*0x10000L);
        matrix.yy = (FT_Fixed)( Math::Cos(rads)*0x10000L);
    }

    FT_Set_Transform(face, &matrix, &pen);

    FT_Error error = FT_Load_Char(face, utf8Character, FT_LOAD_RENDER);
    if (error)
    {
        std::runtime_error("Failed to load glyph");
    }

    character = utf8Character;
    width = face->glyph->bitmap.width;
    height = face->glyph->bitmap.rows;
    advance = Vector2(2,0);//Vector2(face->glyph->advance.x/64.0, face->glyph->advance.y/64.0);
    offset = Vector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
    data = (Byte*)new unsigned char[width*height];
    memcpy(data, face->glyph->bitmap.buffer, width*height);
}
Beispiel #6
0
static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
{
	int iError;
	int iPenX = ptFontBitMap->iCurOriginX;
	int iPenY = ptFontBitMap->iCurOriginY;
#if 0
	FT_Vector tPen;

	tPen.x = 0;
	tPen.y = 0;

	/* set transformation */
	FT_Set_Transform(g_tFace, 0, &tPen);
#endif

	/* load glyph image into the slot (erase previous one) */
	//iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER );
	iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
	if (iError)
	{
		DBG_PRINTF("FT_Load_Char error for code : 0x%x\n", dwCode);
		return -1;
	}

	//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d\n", iPenX, iPenY, g_tSlot->bitmap_left, g_tSlot->bitmap_top, g_tSlot->bitmap.width, g_tSlot->bitmap.rows);
	ptFontBitMap->iXLeft    = iPenX + g_tSlot->bitmap_left;
	ptFontBitMap->iYTop     = iPenY - g_tSlot->bitmap_top;
	ptFontBitMap->iXMax     = ptFontBitMap->iXLeft + g_tSlot->bitmap.width;
	ptFontBitMap->iYMax     = ptFontBitMap->iYTop  + g_tSlot->bitmap.rows;
	ptFontBitMap->iBpp      = 1;
	ptFontBitMap->iPitch    = g_tSlot->bitmap.pitch;
	ptFontBitMap->pucBuffer = g_tSlot->bitmap.buffer;

	ptFontBitMap->iNextOriginX = iPenX + g_tSlot->advance.x / 64;
	ptFontBitMap->iNextOriginY = iPenY;

	//DBG_PRINTF("iXLeft = %d, iYTop = %d, iXMax = %d, iYMax = %d, iNextOriginX = %d, iNextOriginY = %d\n", ptFontBitMap->iXLeft, ptFontBitMap->iYTop, ptFontBitMap->iXMax, ptFontBitMap->iYMax, ptFontBitMap->iNextOriginX, ptFontBitMap->iNextOriginY);

	return 0;
}
JNIEXPORT jdoubleArray JNICALL 
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getMetricsNative
(JNIEnv *env, jobject obj __attribute__((unused)), jint glyphIndex, jlong fnt)
{
  FT_Face ft_face;
  jdouble *values;
  jdoubleArray retArray = NULL;
  PangoFcFont *font;

  font = JLONG_TO_PTR(PangoFcFont, fnt);
  ft_face = pango_fc_font_lock_face( font );

  g_assert (ft_face != NULL);

  FT_Set_Transform( ft_face, NULL, NULL );

  if( FT_Load_Glyph( ft_face, glyphIndex, FT_LOAD_NO_BITMAP ) != 0 )
    {
      pango_fc_font_unlock_face( font );
      printf("Couldn't load glyph %i\n", glyphIndex);
      return NULL;
    }

  retArray = (*env)->NewDoubleArray (env, 8);
  values = (*env)->GetDoubleArrayElements (env, retArray, NULL);

  values[0] = 0;
  values[1] = (jdouble)ft_face->glyph->advance.x/64.0;
  values[2] = (jdouble)ft_face->glyph->advance.y/64.0;
  values[3] = (jdouble)ft_face->glyph->metrics.horiBearingX/64.0;
  values[4] = -(jdouble)ft_face->glyph->metrics.horiBearingY/64.0;
  values[5] = (jdouble)ft_face->glyph->metrics.width/64.0;
  values[6] = (jdouble)ft_face->glyph->metrics.height/64.0;
  values[7] = 0;

  (*env)->ReleaseDoubleArrayElements (env, retArray, values, 0);
  pango_fc_font_unlock_face( font );

  return retArray;
}
Beispiel #8
0
	GlyphMetrics getGlyphMetrics(uint32_t codePoint, Vector2i subpixeloffset64)
	{
		FT_Vector delta;
		delta.x = subpixeloffset64.x;
		delta.y = subpixeloffset64.y;
		FT_Set_Transform(m_face, nullptr, &delta);
		FT_Error error = FT_Load_Glyph(m_face,
		                               codePoint, // the glyph_index in the font file
		                               FT_LOAD_NO_HINTING // by default hb load fonts without hinting
		);
		if (error != FT_Err_Ok)
		{
			debug(LOG_FATAL, "unable to load glyph");
		}

		FT_GlyphSlot slot = m_face->glyph;
		return {
			static_cast<uint32_t>(slot->metrics.width),
			static_cast<uint32_t>(slot->metrics.height),
			slot->bitmap_left, slot->bitmap_top
		};
	}
Beispiel #9
0
// https://github.com/mapnik/mapnik/issues/2578
double font_face::get_ascender()
{
    set_unscaled_character_sizes();
    unsigned glyph_index = FT_Get_Char_Index(face_, 'X');

    FT_Vector pen;
    pen.x = 0;
    pen.y = 0;
    FT_Set_Transform(face_, 0, &pen);
    int e = 0;
    if (!(e = FT_Load_Glyph(face_, glyph_index, FT_LOAD_NO_HINTING)))
    {
        FT_Glyph image;
        if (!FT_Get_Glyph(face_->glyph, &image))
        {
            FT_BBox glyph_bbox;
            FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
            FT_Done_Glyph(image);
            return 64.0 * (glyph_bbox.yMax - glyph_bbox.yMin);
        }
    }
    return face_->ascender;
}
Beispiel #10
0
void text_renderer::prepare_glyphs(glyph_positions const& positions)
{
    FT_Matrix matrix;
    FT_Vector pen;
    FT_Error  error;

    glyphs_.clear();
    glyphs_.reserve(positions.size());

    for (auto const& glyph_pos : positions)
    {
        glyph_info const& glyph = glyph_pos.glyph;
        glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_); //TODO: Optimize this?

        matrix.xx = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L);
        matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L);
        matrix.yx = static_cast<FT_Fixed>( glyph_pos.rot.sin * 0x10000L);
        matrix.yy = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L);

        pixel_position pos = glyph_pos.pos + glyph.offset.rotate(glyph_pos.rot);
        pen.x = static_cast<FT_Pos>(pos.x * 64);
        pen.y = static_cast<FT_Pos>(pos.y * 64);

        FT_Face face = glyph.face->get_face();
        FT_Set_Transform(face, &matrix, &pen);

        error = FT_Load_Glyph(face, glyph.glyph_index, FT_LOAD_NO_HINTING);
        if (error) continue;

        FT_Glyph image;
        error = FT_Get_Glyph(face->glyph, &image);
        if (error) continue;

        glyphs_.emplace_back(image, *glyph.format);
    }
}
Beispiel #11
0
SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
        : SkScalerContext(desc) {
    SkAutoMutexAcquire  ac(gFTMutex);

    if (gFTCount == 0) {
        if (!InitFreetype()) {
            sk_throw();
        }
    }
    ++gFTCount;

    // load the font file
    fFTSize = NULL;
    fFace = NULL;
    fFaceRec = ref_ft_face(fRec.fFontID);
    if (NULL == fFaceRec) {
        return;
    }
    fFace = fFaceRec->fFace;

    // compute our factors from the record

    SkMatrix    m;

    fRec.getSingleMatrix(&m);

#ifdef DUMP_STRIKE_CREATION
    SkString     keyString;
    SkFontHost::GetDescriptorKeyString(desc, &keyString);
    printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
           SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
           SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
           SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
           fRec.getHinting(), fRec.fMaskFormat, keyString.c_str());
#endif

    //  now compute our scale factors
    SkScalar    sx = m.getScaleX();
    SkScalar    sy = m.getScaleY();

    if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
        // sort of give up on hinting
        sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
        sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
        sx = sy = SkScalarAve(sx, sy);

        SkScalar inv = SkScalarInvert(sx);

        // flip the skew elements to go from our Y-down system to FreeType's
        fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
        fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
        fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
        fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
    } else {
        fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
        fMatrix22.xy = fMatrix22.yx = 0;
    }

    fScaleX = SkScalarToFixed(sx);
    fScaleY = SkScalarToFixed(sy);

    // compute the flags we send to Load_Glyph
    {
        FT_Int32 loadFlags = FT_LOAD_DEFAULT;

        if (SkMask::kBW_Format == fRec.fMaskFormat) {
            // See http://code.google.com/p/chromium/issues/detail?id=43252#c24
            loadFlags = FT_LOAD_TARGET_MONO;
            if (fRec.getHinting() == SkPaint::kNo_Hinting)
                loadFlags = FT_LOAD_NO_HINTING;
        } else {
            switch (fRec.getHinting()) {
            case SkPaint::kNo_Hinting:
                loadFlags = FT_LOAD_NO_HINTING;
                break;
            case SkPaint::kSlight_Hinting:
                loadFlags = FT_LOAD_TARGET_LIGHT;  // This implies FORCE_AUTOHINT
                break;
            case SkPaint::kNormal_Hinting:
                loadFlags = FT_LOAD_TARGET_NORMAL;
                break;
            case SkPaint::kFull_Hinting:
                loadFlags = FT_LOAD_TARGET_NORMAL;
                if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat)
                    loadFlags = FT_LOAD_TARGET_LCD;
                else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat)
                    loadFlags = FT_LOAD_TARGET_LCD_V;
                break;
            default:
                SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
                break;
            }
        }

        if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0)
            loadFlags |= FT_LOAD_NO_BITMAP;

        fLoadGlyphFlags = loadFlags;
    }

    // now create the FT_Size

    {
        FT_Error    err;

        err = FT_New_Size(fFace, &fFTSize);
        if (err != 0) {
            SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n",
                        fFaceRec->fFontID, fScaleX, fScaleY, err));
            fFace = NULL;
            return;
        }

        err = FT_Activate_Size(fFTSize);
        if (err != 0) {
            SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
                        fFaceRec->fFontID, fScaleX, fScaleY, err));
            fFTSize = NULL;
        }

        err = FT_Set_Char_Size( fFace,
                                SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY),
                                72, 72);
        if (err != 0) {
            SkDEBUGF(("SkScalerContext_FreeType::FT_Set_Char_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
                        fFaceRec->fFontID, fScaleX, fScaleY, err));
            fFace = NULL;
            return;
        }

        FT_Set_Transform( fFace, &fMatrix22, NULL);
    }
}
Beispiel #12
0
static fz_error *
ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
{
	pdf_font *font = (pdf_font*)fzfont;
	FT_Face face = font->ftface;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	float scale;
	int gid;
	int x, y;
	int hint = font->hint;

	gid = ftcidtogid(font, cid);

	if (font->substitute && fzfont->wmode == 0)
	{
		fz_hmtx subw;
		int realw;

		FT_Set_Char_Size(face, 1000, 1000, 72, 72);

		fterr = FT_Load_Glyph(font->ftface, gid,
				FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
		if (fterr)
			return fz_throw("freetype failed to load glyph: %s", ft_errstr(fterr));

		realw = ((FT_Face)font->ftface)->glyph->advance.x;
		subw = fz_gethmtx(fzfont, cid);
		if (realw)
			scale = (float) subw.w / realw;
		else
			scale = 1.0;

		trm = fz_concat(fz_scale(scale, 1.0), trm);
	}

	glyph->w = 0;
	glyph->h = 0;
	glyph->x = 0;
	glyph->y = 0;
	glyph->samples = nil;

	/* freetype mutilates complex glyphs if they are loaded
	 * with FT_Set_Char_Size 1.0. it rounds the coordinates
	 * before applying transformation. to get more precision in
	 * freetype, we shift part of the scale in the matrix
	 * into FT_Set_Char_Size instead
	 */

#ifdef HINT
	hint = 1;
#endif

	if (hint)
	{
		scale = fz_matrixexpansion(trm);
		m.xx = trm.a * 65536 / scale;
		m.yx = trm.b * 65536 / scale;
		m.xy = trm.c * 65536 / scale;
		m.yy = trm.d * 65536 / scale;
		v.x = 0;
		v.y = 0;

		FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
		FT_Set_Transform(face, &m, &v);

		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
		if (fterr)
			fz_warn("freetype load glyph: %s", ft_errstr(fterr));
	}
	else
	{
		m.xx = trm.a * 64;	/* should be 65536 */
		m.yx = trm.b * 64;
		m.xy = trm.c * 64;
		m.yy = trm.d * 64;
		v.x = trm.e * 64;
		v.y = trm.f * 64;

		FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
		FT_Set_Transform(face, &m, &v);

		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
		if (fterr)
			fz_warn("freetype load glyph: %s", ft_errstr(fterr));
	}

	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (fterr)
		fz_warn("freetype render glyph: %s", ft_errstr(fterr));

	glyph->w = face->glyph->bitmap.width;
	glyph->h = face->glyph->bitmap.rows;
	glyph->x = face->glyph->bitmap_left;
	glyph->y = face->glyph->bitmap_top - glyph->h;
	glyph->samples = face->glyph->bitmap.buffer;

	for (y = 0; y < glyph->h / 2; y++)
	{
		for (x = 0; x < glyph->w; x++)
		{
			unsigned char a = glyph->samples[y * glyph->w + x ];
			unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x];
			glyph->samples[y * glyph->w + x ] = b;
			glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a;
		}
	}

	return fz_okay;
}
TeXFont_PFB::TeXFont_PFB(TeXFontDefinition *parent, fontEncoding *enc, double slant)
  : TeXFont(parent)
{
#ifdef DEBUG_PFB
  if (enc != 0)
    kdDebug(4300) << "TeXFont_PFB::TeXFont_PFB( parent=" << parent << ", encoding=" << enc->encodingFullName << " )" << endl;
  else
    kdDebug(4300) << "TeXFont_PFB::TeXFont_PFB( parent=" << parent << ", encoding=0 )" << endl;
#endif

  fatalErrorInFontLoading = false;

  int error = FT_New_Face( parent->font_pool->FreeType_library, parent->filename.local8Bit(), 0, &face );
  
  if ( error == FT_Err_Unknown_File_Format ) {
    errorMessage = i18n("The font file %1 could be opened and read, but its font format is unsupported.").arg(parent->filename);
    kdError(4300) << errorMessage << endl;
    fatalErrorInFontLoading = true;
    return;
  } else 
    if ( error ) {
      errorMessage = i18n("The font file %1 is broken, or it could not be opened or read.").arg(parent->filename);
      kdError(4300) << errorMessage << endl;
      fatalErrorInFontLoading = true;
      return;
    }

  // Take care of slanting, and transform all characters in the font, if necessary.
  if (slant != 0.0) {
    // Construct a transformation matrix for vertical shear which will
    // be used to transform the characters.
    transformationMatrix.xx = 0x10000;
    transformationMatrix.xy = (FT_Fixed)(slant * 0x10000);
    transformationMatrix.yx = 0;
    transformationMatrix.yy = 0x10000;
    
    FT_Set_Transform( face, &transformationMatrix, 0);
  }
  
  if (face->family_name != 0)
    parent->fullFontName = face->family_name;

  // Finally, we need to set up the charMap array, which maps TeX
  // character codes to glyph indices in the font. (Remark: the
  // charMap, and the font encoding procedure is necessary, because
  // TeX is only able to address character codes 0-255 while
  // e.g. Type1 fonts may contain several thousands of characters)
  if (enc != 0) {
    parent->fullEncodingName = enc->encodingFullName.remove(QString::fromLatin1( "Encoding" ));
    parent->fullEncodingName = enc->encodingFullName.remove(QString::fromLatin1( "encoding" ));

    // An encoding vector is given for this font, i.e. an array of
    // character names (such as: 'parenleft' or 'dotlessj'). We use
    // the FreeType library function 'FT_Get_Name_Index()' to
    // associate glyph indices to those names.
#ifdef DEBUG_PFB
    kdDebug(4300) << "Trying to associate glyph indices to names from the encoding vector." << endl;
#endif
    for(int i=0; i<256; i++) {
      charMap[i] = FT_Get_Name_Index( face, (FT_String *)(enc->glyphNameVector[i].ascii()) );
#ifdef DEBUG_PFB
      kdDebug(4300) << i << ": " << enc->glyphNameVector[i] << ", GlyphIndex=" <<  charMap[i] << endl;
#endif
    }
  } else {
    // If there is no encoding vector available, we check if the font
    // itself contains a charmap that could be used. An admissible
    // charMap will be stored under platform_id=7 and encoding_id=2.
    FT_CharMap  found = 0;
    for (int n = 0; n<face->num_charmaps; n++ ) {
      FT_CharMap charmap = face->charmaps[n];
      if ( charmap->platform_id == 7 && charmap->encoding_id == 2 ) {
	found = charmap;
	break;
      }
    }
    
    if ((found != 0) && (FT_Set_Charmap( face, found ) == 0)) {
      // Feed the charMap array with the charmap data found in the
      // previous step.
#ifdef DEBUG_PFB
      kdDebug(4300) << "No encoding given: using charmap platform=7, encoding=2 that is contained in the font." << endl;
#endif
      for(int i=0; i<256; i++) 
	charMap[i] = FT_Get_Char_Index( face, i );
    } else {
      if ((found == 0) && (face->charmap != 0)) {
#ifdef DEBUG_PFB
	kdDebug(4300) << "No encoding given: using charmap platform=" << face->charmap->platform_id <<
	  ", encoding=" << face->charmap->encoding_id << " that is contained in the font." << endl;
#endif
	for(int i=0; i<256; i++) 
	  charMap[i] = FT_Get_Char_Index( face, i );
      } else {
	// As a last resort, we use the identity map.
#ifdef DEBUG_PFB
	kdDebug(4300) << "No encoding given, no suitable charmaps found in the font: using identity charmap." << endl;
#endif
	for(int i=0; i<256; i++) 
	  charMap[i] = i;
      }
    }
  }
}
Beispiel #14
0
fz_error
fz_renderftglyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm)
{
	FT_Face face = font->ftface;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	int x, y;

#if 0
	/* We lost this feature in refactoring.
	 * We can't access pdf_fontdesc metrics from fz_font.
	 * The pdf_fontdesc metrics are character based (cid),
	 * where the glyph being rendered is given by glyph (gid).
	 */
	if (font->ftsubstitute && font->wmode == 0)
	{
		fz_hmtx subw;
		int realw;
		float scale;

		fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
		if (fterr)
			return fz_warn("freetype setting character size: %s", ft_errorstring(fterr));

		fterr = FT_Load_Glyph(font->ftface, gid,
			FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
		if (fterr)
			return fz_throw("freetype failed to load glyph: %s", ft_errorstring(fterr));

		realw = ((FT_Face)font->ftface)->glyph->advance.x;
		subw = fz_gethmtx(font, cid); // <-- this is the offender
		if (realw)
			scale = (float) subw.w / realw;
		else
			scale = 1.0;

		trm = fz_concat(fz_scale(scale, 1.0), trm);
	}
#endif

	glyph->w = 0;
	glyph->h = 0;
	glyph->x = 0;
	glyph->y = 0;
	glyph->samples = nil;

	/* freetype mutilates complex glyphs if they are loaded
	 * with FT_Set_Char_Size 1.0. it rounds the coordinates
	 * before applying transformation. to get more precision in
	 * freetype, we shift part of the scale in the matrix
	 * into FT_Set_Char_Size instead
	 */

	m.xx = trm.a * 64; /* should be 65536 */
	m.yx = trm.b * 64;
	m.xy = trm.c * 64;
	m.yy = trm.d * 64;
	v.x = trm.e * 64;
	v.y = trm.f * 64;

	fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
	if (fterr)
		fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
	FT_Set_Transform(face, &m, &v);

	if (font->fthint)
	{
		/* Enable hinting, but keep the huge char size so that
		 * it is hinted for a character. This will in effect nullify
		 * the effect of grid fitting. This form of hinting should
		 * only be used for DynaLab and similar tricky TrueType fonts,
		 * so that we get the correct outline shape.
		 */
#ifdef USE_HINTING
		/* If you really want grid fitting, enable this code. */
		float scale = fz_matrixexpansion(trm);
		m.xx = trm.a * 65536 / scale;
		m.xy = trm.b * 65536 / scale;
		m.yx = trm.c * 65536 / scale;
		m.yy = trm.d * 65536 / scale;
		v.x = 0;
		v.y = 0;

		fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
		if (fterr)
			fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
		FT_Set_Transform(face, &m, &v);
#endif
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
		if (fterr)
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
	}
	else
	{
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
		if (fterr)
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
	}

	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (fterr)
		fz_warn("freetype render glyph (gid %d): %s", gid, ft_errorstring(fterr));

	glyph->w = face->glyph->bitmap.width;
	glyph->h = face->glyph->bitmap.rows;
	glyph->x = face->glyph->bitmap_left;
	glyph->y = face->glyph->bitmap_top - glyph->h;
	glyph->samples = face->glyph->bitmap.buffer;

	for (y = 0; y < glyph->h / 2; y++)
	{
		for (x = 0; x < glyph->w; x++)
		{
			unsigned char a = glyph->samples[y * glyph->w + x ];
			unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x];
			glyph->samples[y * glyph->w + x ] = b;
			glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a;
		}
	}

	return fz_okay;
}
Beispiel #15
0
double label_length( char *face_path, int fontsize, char *text)
{
   FT_Library  library;
   FT_Face     face;
   FT_Matrix   matrix;      // transformation matrix
   FT_Vector   pen;

   FT_UInt glyph_index;
   FT_Error error;

   double string_length;
   double xadvance;


   /*Count the length of the string */

   int num_bytes=0;
   while(text[num_bytes]!=0)
        num_bytes++;


   //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file.

   long * ucs4text;

   ucs4text = malloc((num_bytes+1) * sizeof(long));

   unsigned char u,v,w,x,y,z;

   int num_chars=0;

   long iii=0;

   while(iii<num_bytes)
   {
      z = text[iii];

      if(z<=127)
      {
         ucs4text[num_chars] = z;
      }

      if((192<=z)&&(z<=223))
      {
         iii++; y = text[iii];
         ucs4text[num_chars] = (z-192)*64 + (y -128);
      }

      if((224<=z)&&(z<=239))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128);
      }

      if((240<=z)&&(z<=247))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128);
      }

      if((248<=z)&&(z<=251))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         iii++; v = text[iii];
         ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128);
      }

      if((252==z)||(z==253))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         iii++; v = text[iii];
         u = text[iii];
         ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216   + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128);
      }

      if((z==254)||(z==255))
      {
         printf("[struct stat=\"ERROR\", msg=\"Problem with character: invalid UTF-8 data.\"]\n");
         exit(1);
      }
      
      iii++;
      num_chars++;
   }


   // num_chars now contains the number of characters in the string.
   

   /* Initialize FT Library object */

   error = FT_Init_FreeType( &library );

   if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Could not init Library.\"]\n");
      exit(1);
   }


   /* Initialize FT face object */

   error = FT_New_Face( library, face_path, 0, &face );

   if (error == FT_Err_Unknown_File_Format)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Font was opened, but type not supported.\"]\n");
      exit(1);
   }
   else if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Could not find or load font file.\"]\n");
      exit(1);
   }


   /* Set the Char size */

   error = FT_Set_Char_Size( face,          /* handle to face object           */
                             0,             /* char_width in 1/64th of points  */
                             fontsize*64,   /* char_height in 1/64th of points */
                             100,           /* horizontal device resolution    */
                             100 );         /* vertical device resolution      */
   if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Set char size error.\"]\n");
      exit(1);
   }


   int n;

   string_length = 0.;

   for ( n = 0; n < num_chars; n++ )
   {
      /* Convert character code to glyph index */

      glyph_index = FT_Get_Char_Index( face, ucs4text[n] );


      /* Get non-rotated glyph offset (X advance value) */

      matrix.xx = (FT_Fixed)(1.0*0x10000);
      matrix.xy = (FT_Fixed)(0.0*0x10000);
      matrix.yx = (FT_Fixed)(0.0*0x10000);
      matrix.yy = (FT_Fixed)(1.0*0x10000);

      FT_Set_Transform( face, &matrix, &pen );
      FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );

      xadvance = face->glyph->advance.x;

      string_length += xadvance/64.;
   }


   /* Free the face and the library objects */

   FT_Done_Face    ( face );
   FT_Done_FreeType( library );

   free(ucs4text);

   return(string_length);
}
Beispiel #16
0
void FontRenderer::rasterize() {
    clear_bitmaps();
    if (!m_ft_face) {
        return;
    }


    qDebug() << " begin rasterize_font ";



    if (m_config->italic()!=0) {
        FT_Matrix matrix;
        const float angle = (-M_PI*m_config->italic()) / 180.0f;
        matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
        matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
        matrix.yx = (FT_Fixed)( 0/*sin( angle )*/ * 0x10000L );
        matrix.yy = (FT_Fixed)( 1/*cos( angle )*/ * 0x10000L );
        FT_Set_Transform(m_ft_face,&matrix,0);
    } else {
        FT_Set_Transform(m_ft_face,0,0);
    }


    /// fill metrics
    if (FT_IS_SCALABLE(m_ft_face)) {
        m_rendered.metrics.ascender = m_ft_face->size->metrics.ascender / 64;
        m_rendered.metrics.descender = m_ft_face->size->metrics.descender/ 64;
        m_rendered.metrics.height = m_ft_face->size->metrics.height/ 64;
    } else {
        m_rendered.metrics.ascender = m_ft_face->ascender;
        m_rendered.metrics.descender = m_ft_face->descender;
        m_rendered.metrics.height = m_ft_face->height;
    }


    bool use_kerning = FT_HAS_KERNING( m_ft_face );

    const ushort* chars = m_config->characters().utf16();
    size_t amount = 0;
    while (chars[amount]!=0) amount++;
    int error = 0;
    for (size_t i=0;i<amount;i++) {
        int glyph_index = FT_Get_Char_Index( m_ft_face, chars[i] );
        if (glyph_index==0 && !m_config->renderMissing())
            continue;

        FT_Int32 flags = FT_LOAD_DEFAULT;
        if (!m_config->antialiased()) {
            flags = flags | FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO;
        } else {
            flags = flags | FT_LOAD_TARGET_NORMAL;
        }
        switch (m_config->hinting()) {
        case  FontConfig::HintingDisable:
            flags = flags | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
            break;
        case  FontConfig::HintingForceFreetypeAuto:
            flags = flags | FT_LOAD_FORCE_AUTOHINT;
            break;
        case  FontConfig::HintingDisableFreetypeAuto:
            flags = flags | FT_LOAD_NO_AUTOHINT;
            break;
        default:
            break;
        }

        error = FT_Load_Glyph( m_ft_face, glyph_index, flags );
        if ( error )
           continue;
        if (m_config->bold()!=0) {
            FT_Pos strength = m_config->size()*m_config->bold();
            if ( m_ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
                FT_Outline_Embolden( &m_ft_face->glyph->outline, strength );
        }
        if (m_ft_face->glyph->format!=FT_GLYPH_FORMAT_BITMAP) {
            error = FT_Render_Glyph( m_ft_face->glyph,
               m_config->antialiased() ? FT_RENDER_MODE_NORMAL:FT_RENDER_MODE_MONO );
        }
        if ( error )
           continue;
        if (append_bitmap(chars[i])) {
            if (use_kerning)
                append_kerning(chars[i],chars,amount);
        }
    }
    imagesChanged(m_chars);
    imagesChanged();
}
fz_pixmap *
fz_renderftstrokedglyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_strokestate *state)
{
	FT_Face face = font->ftface;
	float expansion = fz_matrixexpansion(ctm);
	int linewidth = state->linewidth * expansion * 64 / 2;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	FT_Stroker stroker;
	FT_Glyph glyph;
	FT_BitmapGlyph bitmap;
	fz_pixmap *pix;
	int y;

	m.xx = trm.a * 64; /* should be 65536 */
	m.yx = trm.b * 64;
	m.xy = trm.c * 64;
	m.yy = trm.d * 64;
	v.x = trm.e * 64;
	v.y = trm.f * 64;

	fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
	if (fterr)
	{
		fz_warn("FT_Set_Char_Size: %s", ft_errorstring(fterr));
		return nil;
	}

	FT_Set_Transform(face, &m, &v);

	fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
	if (fterr)
	{
		fz_warn("FT_Load_Glyph(gid %d): %s", gid, ft_errorstring(fterr));
		return nil;
	}

	fterr = FT_Stroker_New(fz_ftlib, &stroker);
	if (fterr)
	{
		fz_warn("FT_Stroker_New: %s", ft_errorstring(fterr));
		return nil;
	}

	FT_Stroker_Set(stroker, linewidth, state->linecap, state->linejoin, state->miterlimit * 65536);

	fterr = FT_Get_Glyph(face->glyph, &glyph);
	if (fterr)
	{
		fz_warn("FT_Get_Glyph: %s", ft_errorstring(fterr));
		FT_Stroker_Done(stroker);
		return nil;
	}

	fterr = FT_Glyph_Stroke(&glyph, stroker, 1);
	if (fterr)
	{
		fz_warn("FT_Glyph_Stroke: %s", ft_errorstring(fterr));
		FT_Done_Glyph(glyph);
		FT_Stroker_Done(stroker);
		return nil;
	}

	fterr = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
	if (fterr)
	{
		fz_warn("FT_Glyph_To_Bitmap: %s", ft_errorstring(fterr));
		FT_Done_Glyph(glyph);
		FT_Stroker_Done(stroker);
		return nil;
	}

	bitmap = (FT_BitmapGlyph)glyph;
	pix = fz_newpixmap(NULL,
		bitmap->left,
		bitmap->top - bitmap->bitmap.rows,
		bitmap->bitmap.width,
		bitmap->bitmap.rows);

	for (y = 0; y < pix->h; y++)
	{
		memcpy(pix->samples + y * pix->w,
			bitmap->bitmap.buffer + (pix->h - y - 1) * bitmap->bitmap.pitch,
			pix->w);
	}

	FT_Done_Glyph(glyph);
	FT_Stroker_Done(stroker);

	return pix;
}
fz_pixmap *
fz_renderftglyph(fz_font *font, int gid, fz_matrix trm)
{
	FT_Face face = font->ftface;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	fz_pixmap *glyph;
	int y;

	/* Fudge the font matrix to stretch the glyph if we've substituted the font. */
	if (font->ftsubstitute && gid < font->widthcount)
	{
		int subw;
		int realw;
		float scale;

		/* TODO: use FT_Get_Advance */
		fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
		if (fterr)
			fz_warn("freetype setting character size: %s", ft_errorstring(fterr));

		fterr = FT_Load_Glyph(font->ftface, gid,
			FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
		if (fterr)
			fz_warn("freetype failed to load glyph: %s", ft_errorstring(fterr));

		realw = ((FT_Face)font->ftface)->glyph->metrics.horiAdvance;
		subw = font->widthtable[gid];
		if (realw)
			scale = (float) subw / realw;
		else
			scale = 1;

		trm = fz_concat(fz_scale(scale, 1), trm);
	}

	/*
	Freetype mutilates complex glyphs if they are loaded
	with FT_Set_Char_Size 1.0. it rounds the coordinates
	before applying transformation. to get more precision in
	freetype, we shift part of the scale in the matrix
	into FT_Set_Char_Size instead
	*/

	m.xx = trm.a * 64; /* should be 65536 */
	m.yx = trm.b * 64;
	m.xy = trm.c * 64;
	m.yy = trm.d * 64;
	v.x = trm.e * 64;
	v.y = trm.f * 64;

	fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
	if (fterr)
		fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
	FT_Set_Transform(face, &m, &v);

	if (font->fthint)
	{
		/*
		Enable hinting, but keep the huge char size so that
		it is hinted for a character. This will in effect nullify
		the effect of grid fitting. This form of hinting should
		only be used for DynaLab and similar tricky TrueType fonts,
		so that we get the correct outline shape.
		*/
#ifdef GRIDFIT
		/* If you really want grid fitting, enable this code. */
		float scale = fz_matrixexpansion(trm);
		m.xx = trm.a * 65536 / scale;
		m.xy = trm.b * 65536 / scale;
		m.yx = trm.c * 65536 / scale;
		m.yy = trm.d * 65536 / scale;
		v.x = 0;
		v.y = 0;

		fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
		if (fterr)
			fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
		FT_Set_Transform(face, &m, &v);
#endif
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
		if (fterr)
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
	}
	else
	{
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
		if (fterr)
		{
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
			return nil;
		}
	}

	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (fterr)
	{
		fz_warn("freetype render glyph (gid %d): %s", gid, ft_errorstring(fterr));
		return nil;
	}

	glyph = fz_newpixmap(NULL,
		face->glyph->bitmap_left,
		face->glyph->bitmap_top - face->glyph->bitmap.rows,
		face->glyph->bitmap.width,
		face->glyph->bitmap.rows);

	for (y = 0; y < glyph->h; y++)
	{
		memcpy(glyph->samples + y * glyph->w,
			face->glyph->bitmap.buffer + (glyph->h - y - 1) * face->glyph->bitmap.pitch,
			glyph->w);
	}

	return glyph;
}
Beispiel #19
0
    // ------------------------------------------------- texture_font_load_face ---
    static int
    texture_font_load_face(texture_font_t *self, float size,
            FT_Library *library, FT_Face *face)
    {
        FT_Error error;
        FT_Matrix matrix = {
            (int)((1.0/HRES) * 0x10000L),
            (int)((0.0)      * 0x10000L),
            (int)((0.0)      * 0x10000L),
            (int)((1.0)      * 0x10000L)};

        assert(library);
        assert(size);

        /* Initialize library */
        error = FT_Init_FreeType(library);
        if(error) {
			throw;
        }

        /* Load face */
        switch (self->location) {
        case TEXTURE_FONT_FILE:
            error = FT_New_Face(*library, self->filename, 0, face);
            break;

        case TEXTURE_FONT_MEMORY:
            error = FT_New_Memory_Face(*library,
                (const FT_Byte*)self->memory.base, self->memory.size, 0, face);
            break;
        }

        if(error) {
            //fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
            //       __LINE__, FT_Errors[error].code, FT_Errors[error].message);
			FT_Done_FreeType(*library);
			throw;
        }

        /* Select charmap */
        error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
        if(error) {
            FT_Done_Face(*face);
            FT_Done_FreeType(*library);
			throw;
        }

        /* Set char size */
        error = FT_Set_Char_Size(*face, (int)(size * HRES), 0, DPI * HRES, DPI);

        if(error) {
            FT_Done_Face(*face);
            FT_Done_FreeType(*library);
			throw;
        }

        /* Set transform matrix */
        FT_Set_Transform(*face, &matrix, NULL);

        return 1;
    }
Beispiel #20
0
box2d<double> text_renderer<T>::prepare_glyphs(text_path *path)
{
    //clear glyphs
    glyphs_.clear();

    FT_Matrix matrix;
    FT_Vector pen;
    FT_Error  error;

    FT_BBox bbox;
    bbox.xMin = bbox.yMin = 32000;  // Initialize these so we can tell if we
    bbox.xMax = bbox.yMax = -32000; // properly grew the bbox later

    for (int i = 0; i < path->num_nodes(); i++)
    {
        char_info_ptr c;
        double x, y, angle;

        path->vertex(&c, &x, &y, &angle);

        // TODO Enable when we have support for setting verbosity
        // MAPNIK_LOG_DEBUG(font_engine_freetype) << "text_renderer: prepare_glyphs="
        //                                        << c << "," << x << "," << y << "," << angle;

        FT_BBox glyph_bbox;
        FT_Glyph image;

        pen.x = int(x * 64);
        pen.y = int(y * 64);

        face_set_ptr faces = font_manager_.get_face_set(c->format->face_name, c->format->fontset);
        faces->set_character_sizes(c->format->text_size);

        glyph_ptr glyph = faces->get_glyph(unsigned(c->c));
        FT_Face face = glyph->get_face()->get_face();

        matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
        matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
        matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
        matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

        FT_Set_Transform(face, &matrix, &pen);

        error = FT_Load_Glyph(face, glyph->get_index(), FT_LOAD_NO_HINTING);
        if ( error )
            continue;

        error = FT_Get_Glyph(face->glyph, &image);
        if ( error )
            continue;

        FT_Glyph_Get_CBox(image,ft_glyph_bbox_pixels, &glyph_bbox);
        if (glyph_bbox.xMin < bbox.xMin)
            bbox.xMin = glyph_bbox.xMin;
        if (glyph_bbox.yMin < bbox.yMin)
            bbox.yMin = glyph_bbox.yMin;
        if (glyph_bbox.xMax > bbox.xMax)
            bbox.xMax = glyph_bbox.xMax;
        if (glyph_bbox.yMax > bbox.yMax)
            bbox.yMax = glyph_bbox.yMax;

        // Check if we properly grew the bbox
        if ( bbox.xMin > bbox.xMax )
        {
            bbox.xMin = 0;
            bbox.yMin = 0;
            bbox.xMax = 0;
            bbox.yMax = 0;
        }

        // take ownership of the glyph
        glyphs_.push_back(new glyph_t(image, c->format));
    }

    return box2d<double>(bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax);
}
Beispiel #21
0
// ------------------------------------------------------------------- main ---
int main( int argc, char **argv )
{
    size_t i, j;
    int ptSize = 50*64;
    int device_hdpi = 72;
    int device_vdpi = 72;


    glutInit( &argc, argv );
    glutInitWindowSize( 512, 512 );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    glutCreateWindow( argv[0] );
    glutReshapeFunc( reshape );
    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );

#ifndef __APPLE__
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf( stderr, "Error: %s\n", glewGetErrorString(err) );
        exit( EXIT_FAILURE );
    }
    fprintf( stderr, "Using GLEW %s\n", glewGetString(GLEW_VERSION) );
#endif

    texture_atlas_t * atlas = texture_atlas_new( 512, 512, 3 );


    /* Init freetype */
    FT_Library ft_library;
    assert(!FT_Init_FreeType(&ft_library));

    /* Load our fonts */
    FT_Face ft_face[NUM_EXAMPLES];
    assert(!FT_New_Face( ft_library, fonts[ENGLISH], 0, &ft_face[ENGLISH]) );
    assert(!FT_Set_Char_Size( ft_face[ENGLISH], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ENGLISH] );            // wonderful world of encodings ...
    force_ucs2_charmap( ft_face[ENGLISH] ); // which we ignore.

    assert( !FT_New_Face(ft_library, fonts[ARABIC], 0, &ft_face[ARABIC]) );
    assert( !FT_Set_Char_Size(ft_face[ARABIC], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ARABIC] );
    force_ucs2_charmap( ft_face[ARABIC] );

    assert(!FT_New_Face( ft_library, fonts[CHINESE], 0, &ft_face[CHINESE]) );
    assert(!FT_Set_Char_Size( ft_face[CHINESE], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[CHINESE] );
    force_ucs2_charmap( ft_face[CHINESE] );

    /* Get our harfbuzz font structs */
    hb_font_t *hb_ft_font[NUM_EXAMPLES];
    hb_ft_font[ENGLISH] = hb_ft_font_create( ft_face[ENGLISH], NULL );
    hb_ft_font[ARABIC]  = hb_ft_font_create( ft_face[ARABIC] , NULL );
    hb_ft_font[CHINESE] = hb_ft_font_create( ft_face[CHINESE], NULL );

    /* Create a buffer for harfbuzz to use */
    hb_buffer_t *buf = hb_buffer_create();

    for (i=0; i < NUM_EXAMPLES; ++i)
    {
        hb_buffer_set_direction( buf, text_directions[i] ); /* or LTR */
        hb_buffer_set_script( buf, scripts[i] ); /* see hb-unicode.h */
        hb_buffer_set_language( buf,
                                hb_language_from_string(languages[i], strlen(languages[i])) );

        /* Layout the text */
        hb_buffer_add_utf8( buf, texts[i], strlen(texts[i]), 0, strlen(texts[i]) );
        hb_shape( hb_ft_font[i], buf, NULL, 0 );

        unsigned int         glyph_count;
        hb_glyph_info_t     *glyph_info   = hb_buffer_get_glyph_infos(buf, &glyph_count);
        hb_glyph_position_t *glyph_pos    = hb_buffer_get_glyph_positions(buf, &glyph_count);


        FT_GlyphSlot slot;
        FT_Bitmap ft_bitmap;
        float size = 24;
        size_t hres = 64;
        FT_Error error;
        FT_Int32 flags = 0;
        flags |= FT_LOAD_RENDER;
        flags |= FT_LOAD_TARGET_LCD;
        FT_Library_SetLcdFilter( ft_library, FT_LCD_FILTER_LIGHT );
        FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((1.0)      * 0x10000L) };
        /* Set char size */
        error = FT_Set_Char_Size( ft_face[i], (int)(ptSize), 0, 72*hres, 72 );
        if( error )
        {
            //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
            //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
            FT_Done_Face( ft_face[i] );
            break;
        }

        /* Set transform matrix */
        FT_Set_Transform( ft_face[i], &matrix, NULL );

        for (j = 0; j < glyph_count; ++j)
        {
            /* Load glyph */
            error = FT_Load_Glyph( ft_face[i], glyph_info[j].codepoint, flags );
            if( error )
            {
                //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
                FT_Done_Face( ft_face[i] );
                break;
            }

            slot = ft_face[i]->glyph;
            ft_bitmap = slot->bitmap;
            int ft_bitmap_width = slot->bitmap.width;
            int ft_bitmap_rows  = slot->bitmap.rows;
            int ft_bitmap_pitch = slot->bitmap.pitch;
            int ft_glyph_top    = slot->bitmap_top;
            int ft_glyph_left   = slot->bitmap_left;

            int w = ft_bitmap_width/3; // 3 because of LCD/RGB encoding
            int h = ft_bitmap_rows;

            ivec4 region = texture_atlas_get_region( atlas, w+1, h+1 );
            if ( region.x < 0 )
            {
                fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
                continue;
            }
            int x = region.x, y = region.y;
            texture_atlas_set_region( atlas, region.x, region.y,
                                      w, h, ft_bitmap.buffer, ft_bitmap.pitch );
            printf("%d: %dx%d %f %f\n",
                   glyph_info[j].codepoint,
                   ft_bitmap_width,
                   ft_bitmap_rows,
                   glyph_pos[j].x_advance/64.,
                   glyph_pos[j].y_advance/64.);
        }

        /* clean up the buffer, but don't kill it just yet */
        hb_buffer_reset(buf);
    }


    /* Cleanup */
    hb_buffer_destroy( buf );
    for( i=0; i < NUM_EXAMPLES; ++i )
        hb_font_destroy( hb_ft_font[i] );
    FT_Done_FreeType( ft_library );

    glClearColor(1,1,1,1);
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable( GL_TEXTURE_2D );

    glBindTexture( GL_TEXTURE_2D, atlas->id );
    texture_atlas_upload( atlas );

    typedef struct { float x,y,z, u,v, r,g,b,a, shift, gamma; } vertex_t;
    vertex_t vertices[4] =  {
        {  0,  0,0, 0,1, 0,0,0,1, 0, 1},
        {  0,512,0, 0,0, 0,0,0,1, 0, 1},
        {512,512,0, 1,0, 0,0,0,1, 0, 1},
        {512,  0,0, 1,1, 0,0,0,1, 0, 1} };
    GLuint indices[6] = { 0, 1, 2, 0,2,3 };
    buffer = vertex_buffer_new( "vertex:3f,"
                                "tex_coord:2f,"
                                "color:4f,"
                                "ashift:1f,"
                                "agamma:1f" );






    vertex_buffer_push_back( buffer, vertices, 4, indices, 6 );
    shader = shader_load("shaders/text.vert", "shaders/text.frag");
    mat4_set_identity( &projection );
    mat4_set_identity( &model );
    mat4_set_identity( &view );
    glutMainLoop( );
    return 0;
}
Beispiel #22
0
void labeled_curve( char *face_path, int fontsize, int showLine,
                    double *xcurve, double *ycurve, int npt,  
                    char *text, double offset, 
                    double red, double green, double blue)
{
   FT_Library  library;
   FT_Face     face;
   FT_Matrix   matrix;      // transformation matrix
   FT_Vector   pen;

   FT_UInt glyph_index;
   FT_Error error;

   FT_Bool use_kerning;
   FT_UInt previous = 0;

   int    npath;
   double x1, y1;
   double x2, y2;
   double path_length1, path_length2;

   int    npath_ang;
   double x1_ang, y1_ang;
   double x2_ang, y2_ang;
   double path_length1_ang, path_length2_ang;

   double xchar, ychar;
   double delx, dely;
   double xadvance;
   double angle, dl, frac, length;
   double xoff, yoff;
   double dtr;

   int xpix, ypix;
   int ii, jj;

   dtr = atan(1.)/45.;

   if(npt < 2)
      return;


   /* Draw the curve up to the text starting offset */

   x1 = xcurve[0];
   y1 = ycurve[0];

   x2 = xcurve[1];
   y2 = ycurve[1];

   path_length1 = 0;
   path_length2 = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));

   npath = 1;

   while(path_length2 < offset)
   {
      if(showLine)
      {
         smooth_line(x1, y1, x2, y2, red, green, blue);
      }

      ++npath;
      if(npath >= npt)
         break;

      x1 = x2;
      y1 = y2;

      x2 = xcurve[npath];
      y2 = ycurve[npath];

      path_length1  = path_length2;
      path_length2 += sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
   }


   /* Find the angle for the text */

   angle = atan2((y2-y1), (x2-x1));

   xoff =  0.4 * (double)fontsize * sin(angle);
   yoff = -0.4 * (double)fontsize * cos(angle);


   /* Interpolate the last curve segment before the text and draw a subsegment */

   frac = (offset - path_length1) / (path_length2 - path_length1);

   xchar = x1 + frac * (x2 - x1);
   ychar = y1 + frac * (y2 - y1);
      
   if(frac > 0 && showLine)
   {
      smooth_line(x1, y1, xchar, ychar, red, green, blue);
   }

   xpix = floor(xchar + xoff);
   ypix = floor(ychar + yoff);

   pen.x = (xchar + xoff - (double)xpix) * 64.;
   pen.y = (ychar + yoff - (double)ypix) * 64.;


   /* Now draw characters, each one oriented based on the slope and location */
   /* of the curve at that point.  If we run out of curve before we run out  */
   /* of characters, extrapolate based on the last slope/location            */

   /* Place starting coordinates in adequate form. */

   length = 0.;


   /*Count the length of the string */

   int num_bytes=0;
   while(text[num_bytes]!=0)
        num_bytes++;


   //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file.

   long * ucs4text;

   ucs4text = malloc((num_bytes+1) * sizeof(long));

   unsigned char u,v,w,x,y,z;

   int num_chars=0;

   long iii=0;

   while(iii<num_bytes)
   {
      z = text[iii];

      if(z<=127)
      {
         ucs4text[num_chars] = z;
      }

      if((192<=z)&&(z<=223))
      {
         iii++; y = text[iii];
         ucs4text[num_chars] = (z-192)*64 + (y -128);
      }

      if((224<=z)&&(z<=239))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         ucs4text[num_chars] = (z-224)*4096 + (y -128)*64 + (x-128);
      }

      if((240<=z)&&(z<=247))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         ucs4text[num_chars] = (z-240)*262144 + (y -128)*4096 + (x-128)*64 + (w-128);
      }

      if((248<=z)&&(z<=251))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         iii++; v = text[iii];
         ucs4text[num_chars] = (z-248)*16777216 + (y -128)*262144 + (x-128)*4096 + (w-128)*64 +(v-128);
      }

      if((252==z)||(z==253))
      {
         iii++; y = text[iii];
         iii++; x = text[iii];
         iii++; w = text[iii];
         iii++; v = text[iii];
         u = text[iii];
         ucs4text[num_chars] = (z-252)*1073741824 + (y -128)*16777216   + (x-128)*262144 + (w-128)*4096 +(v-128)*64 + (u-128);
      }

      if((z==254)||(z==255))
      {
         printf("[struct stat=\"ERROR\", msg=\"Problem with character: invalid UTF-8 data.\"]\n");
         exit(1);
      }
      
      iii++;
      num_chars++;
   }


   // num_chars now contains the number of characters in the string.
   

   /* Initialize FT Library object */

   error = FT_Init_FreeType( &library );

   if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Could not init Library.\"]\n");
      exit(1);
   }


   /* Initialize FT face object */

   error = FT_New_Face( library, face_path, 0, &face );

   if (error == FT_Err_Unknown_File_Format)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Font was opened, but type not supported.\"]\n");
      exit(1);
   }
   else if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Could not find or load font file.\"]\n");
      exit(1);
   }


   /* Set the Char size */

   error = FT_Set_Char_Size( face,          /* handle to face object           */
                             0,             /* char_width in 1/64th of points  */
                             fontsize*64,   /* char_height in 1/64th of points */
                             100,           /* horizontal device resolution    */
                             100 );         /* vertical device resolution      */
   if (error)
   {
      printf("[struct stat=\"ERROR\", msg=\"FreeType: Set char size error.\"]\n");
      exit(1);
   }


   /* Does the font file support kerning? */

   use_kerning = FT_HAS_KERNING( face );

   int n;
   for ( n = 0; n < num_chars; n++ )
   {
      /* Convert character code to glyph index */

      glyph_index = FT_Get_Char_Index( face, ucs4text[n] );


      /* Get non-rotated glyph offset (X advance value) */

      matrix.xx = (FT_Fixed)(1.0*0x10000);
      matrix.xy = (FT_Fixed)(0.0*0x10000);
      matrix.yx = (FT_Fixed)(0.0*0x10000);
      matrix.yy = (FT_Fixed)(1.0*0x10000);

      FT_Set_Transform( face, &matrix, &pen );
      FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );

      xadvance = face->glyph->advance.x;


      /* Find the angle for this character (calculated at center of character) */

      npath_ang = npath;

      x1_ang = x1;
      y1_ang = y1;

      x2_ang = x2;
      y2_ang = y2;

      path_length2_ang = path_length2;

      while(path_length2_ang < offset+length+xadvance/64./2.)
      {
         ++npath_ang;
         if(npath_ang >= npt)
            break;

         x1_ang = x2_ang;
         y1_ang = y2_ang;

         x2_ang = xcurve[npath_ang];
         y2_ang = ycurve[npath_ang];

         path_length1_ang  = path_length2_ang;
         path_length2_ang += sqrt((x2_ang-x1_ang)*(x2_ang-x1_ang) + (y2_ang-y1_ang)*(y2_ang-y1_ang));
      }

      angle = atan2((y2_ang-y1_ang), (x2_ang-x1_ang));


      /* Retrieve kerning distance (if any) and move pen position */

      delx = 0.;
      dely = 0.;

      if ( use_kerning && previous && glyph_index )
      {
         FT_Vector  delta;
         FT_Get_Kerning( face,
                         previous,
                         glyph_index,
                         ft_kerning_default, //FT_KERNING_DEFAULT,
                         &delta );


         /* Transform this kerning distance into rotated space */

         pen.x += (int) (((double) delta.x)*cos(angle));
         pen.y += (int) (((double) delta.x)*sin(angle));

         if(pen.x >= 64)
         {
            ++xpix;
            pen.x -= 64;
         }

         if(pen.y >= 64)
         {
            ++ypix;
            pen.y -= 64;
         }

         delx = ((double) delta.x)*cos(angle);
         dely = ((double) delta.y)*sin(angle);
      }


      /* Set transform */

      matrix.xx = (FT_Fixed)( cos(angle)*0x10000);
      matrix.xy = (FT_Fixed)(-sin(angle)*0x10000);
      matrix.yx = (FT_Fixed)( sin(angle)*0x10000);
      matrix.yy = (FT_Fixed)( cos(angle)*0x10000);

      FT_Set_Transform( face, &matrix, &pen );


      /* Retrieve glyph index from character code */

      glyph_index = FT_Get_Char_Index( face, ucs4text[n] );


      /* Load glyph image (erase previous one) */

      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );

      if (error)
      {
         printf("[struct stat=\"ERROR\", msg=\"FreeType: Could not load glyph (in loop).\"]\n");
         exit(1);
      }


      /* Convert to an anti-aliased bitmap */

      error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );

      if (error)
      {
         printf("[struct stat=\"ERROR\", msg=\"FreeType: Render glyph error.\"]\n");
         exit(1);
      }


      /* Now, draw to our target surface */

      draw_bitmap( &face->glyph->bitmap,
                      xpix + face->glyph->bitmap_left,
                      ypix + face->glyph->bitmap_top,
                      red, green, blue, fontsize);


      /* Advance to the next position */

      delx += face->glyph->advance.x;
      dely += face->glyph->advance.y;

      dl = sqrt((delx/64.)*(delx/64.) + (dely/64.)*(dely/64.));

      length += dl;


      /* Find the start location for the next character */

      while(path_length2 < offset+length)
      {
         ++npath;
         if(npath >= npt)
            break;

         x1 = x2;
         y1 = y2;

         x2 = xcurve[npath];
         y2 = ycurve[npath];

         path_length1  = path_length2;
         path_length2 += sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
      }


      /* Interpolate the current curve segment */
   
      frac = (offset+length - path_length1) / (path_length2 - path_length1);
   
      xchar = x1 + frac * (x2 - x1);
      ychar = y1 + frac * (y2 - y1);

      xpix = floor(xchar);
      ypix = floor(ychar);


      /* Draw character reference point (for debugging purposes) **

      for(ii=xpix-1; ii<=xpix+1; ++ii)
         for(jj=ypix-1; jj<=ypix+1; ++jj)
            setPixel(ii, jj, 1., 0., 0., 1., 1);

      ***/

      xpix = floor(xchar+xoff);
      ypix = floor(ychar+yoff);

      pen.x = (xchar + xoff - (double)xpix) * 64.;
      pen.y = (ychar + yoff - (double)ypix) * 64.;

      xoff =  0.4 * (double)fontsize * sin(angle);
      yoff = -0.4 * (double)fontsize * cos(angle);


      /* record current glyph index (needed for kerning next glyph) */

      previous = glyph_index;
   }


   /* Free the face and the library objects */

   FT_Done_Face    ( face );
   FT_Done_FreeType( library );


   /* Draw the subsegment of the curve following the last character */

   if(showLine && npath < npt)
   {
      smooth_line(xchar, ychar, x2, y2, red, green, blue);
   }


   /* Finally, draw the remainder of the curve */

   while(1)
   {
      if(showLine)
      {
         smooth_line(x1, y1, x2, y2, red, green, blue);
      }

      ++npath;
      if(npath >= npt)
         break;

      x1 = x2;
      y1 = y2;

      x2 = xcurve[npath];
      y2 = ycurve[npath];
   }

   free(ucs4text);
}
// ------------------------------------------------------------------- init ---
void init( void )
{
    size_t i, j;
    int ptSize = 50*64;
    int device_hdpi = 72;
    int device_vdpi = 72;

    atlas = texture_atlas_new( 512, 512, 3 );

    /* Init freetype */
    FT_Library ft_library;
    assert(!FT_Init_FreeType(&ft_library));

    /* Load our fonts */
    FT_Face ft_face[NUM_EXAMPLES];
    assert(!FT_New_Face( ft_library, fonts[ENGLISH], 0, &ft_face[ENGLISH]) );
    assert(!FT_Set_Char_Size( ft_face[ENGLISH], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ENGLISH] );            // wonderful world of encodings ...
    force_ucs2_charmap( ft_face[ENGLISH] ); // which we ignore.

    assert( !FT_New_Face(ft_library, fonts[ARABIC], 0, &ft_face[ARABIC]) );
    assert( !FT_Set_Char_Size(ft_face[ARABIC], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[ARABIC] );
    force_ucs2_charmap( ft_face[ARABIC] );

    assert(!FT_New_Face( ft_library, fonts[CHINESE], 0, &ft_face[CHINESE]) );
    assert(!FT_Set_Char_Size( ft_face[CHINESE], 0, ptSize, device_hdpi, device_vdpi ) );
    // ftfdump( ft_face[CHINESE] );
    force_ucs2_charmap( ft_face[CHINESE] );

    /* Get our harfbuzz font structs */
    hb_font_t *hb_ft_font[NUM_EXAMPLES];
    hb_ft_font[ENGLISH] = hb_ft_font_create( ft_face[ENGLISH], NULL );
    hb_ft_font[ARABIC]  = hb_ft_font_create( ft_face[ARABIC] , NULL );
    hb_ft_font[CHINESE] = hb_ft_font_create( ft_face[CHINESE], NULL );

    /* Create a buffer for harfbuzz to use */
    hb_buffer_t *buf = hb_buffer_create();

    for (i=0; i < NUM_EXAMPLES; ++i)
    {
        hb_buffer_set_direction( buf, text_directions[i] ); /* or LTR */
        hb_buffer_set_script( buf, scripts[i] ); /* see hb-unicode.h */
        hb_buffer_set_language( buf,
                                hb_language_from_string(languages[i], strlen(languages[i])) );

        /* Layout the text */
        hb_buffer_add_utf8( buf, texts[i], strlen(texts[i]), 0, strlen(texts[i]) );
        hb_shape( hb_ft_font[i], buf, NULL, 0 );

        unsigned int         glyph_count;
        hb_glyph_info_t     *glyph_info   = hb_buffer_get_glyph_infos(buf, &glyph_count);
        hb_glyph_position_t *glyph_pos    = hb_buffer_get_glyph_positions(buf, &glyph_count);


        FT_GlyphSlot slot;
        FT_Bitmap ft_bitmap;
        float size = 24;
        size_t hres = 64;
        FT_Error error;
        FT_Int32 flags = 0;
        flags |= FT_LOAD_RENDER;
        flags |= FT_LOAD_TARGET_LCD;
        FT_Library_SetLcdFilter( ft_library, FT_LCD_FILTER_LIGHT );
        FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((0.0)      * 0x10000L),
                             (int)((1.0)      * 0x10000L) };
        /* Set char size */
        error = FT_Set_Char_Size( ft_face[i], (int)(ptSize), 0, 72*hres, 72 );
        if( error )
        {
            //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
            //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
            FT_Done_Face( ft_face[i] );
            break;
        }

        /* Set transform matrix */
        FT_Set_Transform( ft_face[i], &matrix, NULL );

        for (j = 0; j < glyph_count; ++j)
        {
            /* Load glyph */
            error = FT_Load_Glyph( ft_face[i], glyph_info[j].codepoint, flags );
            if( error )
            {
                //fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                //         __LINE__, FT_Errors[error].code, FT_Errors[error].message );
                FT_Done_Face( ft_face[i] );
                break;
            }

            slot = ft_face[i]->glyph;
            ft_bitmap = slot->bitmap;
            int ft_bitmap_width = slot->bitmap.width;
            int ft_bitmap_rows  = slot->bitmap.rows;
            int ft_bitmap_pitch = slot->bitmap.pitch;
            int ft_glyph_top    = slot->bitmap_top;
            int ft_glyph_left   = slot->bitmap_left;

            int w = ft_bitmap_width/3; // 3 because of LCD/RGB encoding
            int h = ft_bitmap_rows;

            ivec4 region = texture_atlas_get_region( atlas, w+1, h+1 );
            if ( region.x < 0 )
            {
                fprintf( stderr, "Texture atlas is full (line %d)\n",  __LINE__ );
                continue;
            }
            int x = region.x, y = region.y;
            texture_atlas_set_region( atlas, region.x, region.y,
                                      w, h, ft_bitmap.buffer, ft_bitmap.pitch );
            printf("%d: %dx%d %f %f\n",
                   glyph_info[j].codepoint,
                   ft_bitmap_width,
                   ft_bitmap_rows,
                   glyph_pos[j].x_advance/64.,
                   glyph_pos[j].y_advance/64.);
        }

        /* clean up the buffer, but don't kill it just yet */
        hb_buffer_reset(buf);
    }


    /* Cleanup */
    hb_buffer_destroy( buf );
    for( i=0; i < NUM_EXAMPLES; ++i )
        hb_font_destroy( hb_ft_font[i] );
    FT_Done_FreeType( ft_library );

    glClearColor(1,1,1,1);
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glGenTextures( 1, &atlas->id );
    glBindTexture( GL_TEXTURE_2D, atlas->id );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, atlas->width, atlas->height,
                  0, GL_RGB, GL_UNSIGNED_BYTE, atlas->data );

    typedef struct { float x,y,z, u,v, r,g,b,a, shift, gamma; } vertex_t;
    vertex_t vertices[4] =  {
        {  0,  0,0, 0,1, 0,0,0,1, 0, 1},
        {  0,512,0, 0,0, 0,0,0,1, 0, 1},
        {512,512,0, 1,0, 0,0,0,1, 0, 1},
        {512,  0,0, 1,1, 0,0,0,1, 0, 1} };
    GLuint indices[6] = { 0, 1, 2, 0,2,3 };
    buffer = vertex_buffer_new( "vertex:3f,"
                                "tex_coord:2f,"
                                "color:4f,"
                                "ashift:1f,"
                                "agamma:1f" );
    vertex_buffer_push_back( buffer, vertices, 4, indices, 6 );

    shader = shader_load("shaders/text.vert",
                         "shaders/text.frag");
    mat4_set_identity( &projection );
    mat4_set_identity( &model );
    mat4_set_identity( &view );
}
static BOOL ft_get_char(void *p_priv,
  u16 char_code, rsc_fstyle_t *p_fstyle, rsc_char_info_t *p_info)
{
  RET_CODE ret = SUCCESS;
  ft_cache_t *p_vf_cache = NULL;
  u32 i = 0, ckey = 0;
  ft_priv_t *p_vf = (ft_priv_t *)p_priv;
  FT_Stroker p_stroker = {0};
  FT_Raster_Params params = {0};  
  FT_Glyph p_glyph = {0};
  spans_t spans = {0};
  FT_BBox bbox_fg = {0}, bbox_bg = {0};
  u16 w_bg = 0, w_fg = 0, h_bg = 0, h_fg = 0;
  FT_Matrix matrix = {0};
  rsc_font_t hdr_font = {{0}};
  u8 *p_font = NULL;

  MT_ASSERT(p_vf != NULL);

  if(ft_hit_cache(p_priv, char_code, p_fstyle, p_info))
  {
    p_info->ckey = p_fstyle->color ? 0 : 1;
    p_info->bpp = p_vf->bpp;
    
    return TRUE;
  }

  MT_ASSERT(p_fstyle->width <= p_vf->max_width);
  MT_ASSERT(p_fstyle->height <= p_vf->max_height);
  
  if(!rsc_get_font(p_vf->rsc_handle, p_fstyle->font_id, &hdr_font, &p_font))
  {
    return FALSE;
  }

  MT_ASSERT(hdr_font.type == FONT_VECTOR);

  if(!ft_check_char(p_priv, char_code, p_font, hdr_font.head.org_size, p_fstyle))
  {
    return FALSE;
  }

  p_vf_cache = ft_insert_cache(p_priv, char_code, p_fstyle);

  ckey = p_fstyle->color ? 0 : 1;

  MT_ASSERT(p_vf_cache != NULL);

  
  if((p_fstyle->attr & VFONT_ITALIC) != 0)
  {
    matrix.xx = 0x10000L;
    matrix.xy = 0x1000L;
    matrix.yx = 0;
    matrix.yy = 0x10000L;
    FT_Set_Transform(p_vf->p_face, &matrix, 0);  
  }
  else
  {
    FT_Set_Transform(p_vf->p_face, NULL, 0);  
  }

  ret = FT_Set_Pixel_Sizes(p_vf->p_face, p_vf_cache->char_width, p_vf_cache->char_height);
  MT_ASSERT(ret == SUCCESS);

  if(((p_fstyle->attr & VFONT_STROK) == 0) || (p_vf->is_alpha_spt == FALSE))
  {
    if(p_vf->is_alpha_spt)
    {
      ret = FT_Load_Char(p_vf->p_face, char_code, FT_LOAD_RENDER);
      p_info->is_alpha_spt = TRUE;    
    }
    else
    {
      ret = FT_Load_Char(p_vf->p_face, char_code, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
      p_info->is_alpha_spt = FALSE;
    }

    if((p_fstyle->attr & VFONT_BOLD) != 0)
    {
      FT_Bitmap_Embolden(p_vf->p_library, &p_vf->p_face->glyph->bitmap, 64, 64);    
    }
    
    MT_ASSERT(ret == SUCCESS);

    p_info->height = p_vf->p_face->glyph->bitmap.rows;
    p_info->width = p_vf->p_face->glyph->bitmap.width;
    p_info->xoffset = p_vf->p_face->glyph->bitmap_left;
    p_info->yoffset = ((p_vf->p_face->size->metrics.ascender
     - p_vf->p_face->glyph->metrics.horiBearingY) >> 6);
    p_info->pitch = p_vf->max_width * p_vf->bpp >> 3;
    p_info->alpha_pitch = p_vf->max_width;
    p_info->x_step = ((p_vf->p_face->glyph->advance.x) >> 6);
    p_info->step_width = p_vf->p_face->glyph->metrics.horiAdvance >> 6;
    //p_info->step_height = p_vf->p_face->size->metrics.y_ppem;
    p_info->step_height = p_vf->p_face->size->metrics.height >> 6;

    p_vf_cache->pitch = p_info->pitch;
    p_vf_cache->alpha_pitch = p_info->alpha_pitch;
    p_vf_cache->xoff = p_info->xoffset;
    p_vf_cache->yoff = p_info->yoffset;
    p_vf_cache->step_width = p_info->step_width;
    p_vf_cache->step_height = p_info->step_height;
    p_vf_cache->x_step = p_info->x_step;
    p_vf_cache->width = p_info->width;
    p_vf_cache->height = p_info->height;  
    p_vf_cache->color = p_fstyle->color;
    
    if(p_vf->is_alpha_spt)
    {
      for(i = 0; i < p_vf->p_face->glyph->bitmap.rows; i++)
      {
        memcpy((u8 *)p_vf_cache->p_alpha + i * p_vf->max_width,
          p_vf->p_face->glyph->bitmap.buffer + i * p_vf->p_face->glyph->bitmap.pitch,
          p_vf->p_face->glyph->bitmap.pitch);
      }

      for(i = 0; i < (p_vf->max_height * p_vf->max_width); i++)
      {
        if(p_vf->bpp == 32)
        {
          *((u32 *)(p_vf_cache->p_char) + i) = p_fstyle->color;
        }
        else if(p_vf->bpp == 16)
        {
          *((u16 *)(p_vf_cache->p_char) + i) = p_fstyle->color;
        }
        
      }    
    }
    else
    {
      if(p_vf->bpp == 32)
      {
        mono_to_u32buf(p_vf->p_face->glyph->bitmap.buffer,
          p_vf->p_face->glyph->bitmap.width, p_vf->p_face->glyph->bitmap.rows,
          p_vf->p_face->glyph->bitmap.pitch,
          p_vf_cache->p_char, p_vf->max_width * 4, p_fstyle->color, ckey);
      }
      else if(p_vf->bpp == 16)
      {
        mono_to_u16buf(p_vf->p_face->glyph->bitmap.buffer,
          p_vf->p_face->glyph->bitmap.width, p_vf->p_face->glyph->bitmap.rows,
          p_vf->p_face->glyph->bitmap.pitch,
          p_vf_cache->p_char, p_vf->max_width * 2, p_fstyle->color, ckey);
      }
    }

    p_info->p_alpha = p_vf_cache->p_alpha;
    p_info->p_char = p_vf_cache->p_char;
    p_info->p_strok_alpha = NULL;
    p_info->p_strok_char = NULL;
  }
  else if((p_fstyle->attr & VFONT_STROK) != 0)  
Beispiel #25
0
int
main( int     argc,
      char**  argv )
{
  FT_Library    library;
  FT_Face       face;

  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;

  char*         filename;
//  char*         text;

  double        angle;
  int           target_height;
  int           n, num_chars;

  wchar_t *chinese_str = L"ол╣Щ1g";
  unsigned int *p = (unsigned int *)chinese_str;
  int i;

  printf("Uniocde: \n");
  for (i = 0; i < wcslen(chinese_str); i++)
  {
  	printf("0x%x ", p[i]);
  }
  printf("\n");
//  return 0;


  if ( argc != 2 )
  {
    fprintf ( stderr, "usage: %s font\n", argv[0] );
    exit( 1 );
  }

  filename      = argv[1];                           /* first argument     */
//  text          = argv[2];                           /* second argument    */
  num_chars     = wcslen(chinese_str);
  angle         = ( 0.0 / 360 ) * 3.14159 * 2;      /* use 0 degrees     */
  target_height = HEIGHT;

  error = FT_Init_FreeType( &library );              /* initialize library */
  /* error handling omitted */

  error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
  /* error handling omitted */

  /* use 20pt at 100dpi */
  error = FT_Set_Char_Size( face, 20 * 64, 0,
                            100, 0 );                /* set character size */
  /* error handling omitted */

  slot = face->glyph;

  /* set up matrix */
  matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
  matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
  matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
  matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

  /* the pen position in 26.6 cartesian space coordinates; */
  /* start at (0,40) relative to the upper left corner  */
  pen.x = 0 * 64;
  pen.y = ( target_height - 40 ) * 64;

  for ( n = 0; n < num_chars; n++ )
  {
    /* set transformation */
    FT_Set_Transform( face, &matrix, &pen );

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER );
    if ( error )
      continue;                 /* ignore errors */

    /* now, draw to our target surface (convert position) */
    draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 target_height - slot->bitmap_top );

    /* increment pen position */
    pen.x += slot->advance.x;
    pen.y += slot->advance.y;
  }

  show_image();

  FT_Done_Face    ( face );
  FT_Done_FreeType( library );

  return 0;
}
Beispiel #26
0
unsigned char *gks_ft_get_bitmap(int *x, int *y, int *width, int *height,
                                 gks_state_list_t *gkss, const char *text,
                                 int length) {
  FT_Face face;                   /* font face */
  FT_Vector pen;                  /* glyph position */
  FT_BBox bb;                     /* bounding box */
  FT_Vector bearing;              /* individual glyph translation */
  FT_UInt previous;               /* previous glyph index */
  FT_Vector spacing;              /* amount of additional space between glyphs */
  FT_ULong textheight;            /* textheight in FreeType convention */
  FT_Error error;                 /* error code */
  FT_Matrix rotation;             /* text rotation matrix */
  FT_UInt size;                   /* number of pixels of the bitmap */
  FT_String *file;                /* concatenated font path */
  const FT_String *font, *prefix; /* font file name and directory */
  FT_UInt *unicode_string;        /* unicode text string */
  FT_Int halign, valign;          /* alignment */
  FT_Byte *mono_bitmap = NULL;    /* target for rendered text */
  FT_Int num_glyphs;              /* number of glyphs */
  FT_Vector align;
  FT_Bitmap ftbitmap;
  FT_UInt codepoint;
  int i, textfont, dx, dy, value, pos_x, pos_y;
  unsigned int j, k;
  double angle;
  const int windowwidth = *width;
  const int direction = (gkss->txp <= 3 && gkss->txp >= 0 ? gkss->txp : 0);
  const FT_Bool vertical = (direction == GKS_K_TEXT_PATH_DOWN ||
                            direction == GKS_K_TEXT_PATH_UP);
  const FT_String *suffix_type1 = ".afm";

  if (!init) gks_ft_init();

  if (gkss->txal[0] != GKS_K_TEXT_HALIGN_NORMAL) {
    halign = gkss->txal[0];
  } else if (vertical) {
    halign = GKS_K_TEXT_HALIGN_CENTER;
  } else if (direction == GKS_K_TEXT_PATH_LEFT) {
    halign = GKS_K_TEXT_HALIGN_RIGHT;
  } else {
    halign = GKS_K_TEXT_HALIGN_LEFT;
  }
  valign = gkss->txal[1];
  if (valign != GKS_K_TEXT_VALIGN_NORMAL) {
    valign = gkss->txal[1];
  } else {
    valign = GKS_K_TEXT_VALIGN_BASE;
  }

  textfont = abs(gkss->txfont);
  if (textfont >= 101 && textfont <= 131)
    textfont -= 100;
  else if (textfont > 1 && textfont <= 32)
    textfont = map[textfont - 1];
  else
    textfont = 9;

  textfont = textfont - 1;
  font = gks_font_list[textfont];

  if (font_face_cache[textfont] == NULL) {
    prefix = gks_getenv("GKS_FONTPATH");
    if (prefix == NULL) {
      prefix = gks_getenv("GRDIR");
      if (prefix == NULL)
        prefix = GRDIR;
    }
    file = (FT_String *) malloc(strlen(prefix) + 7 + strlen(font) + 4 + 1);
    strcpy(file, prefix);
#ifndef _WIN32
    strcat(file, "/fonts/");
#else
    strcat(file, "\\FONTS\\");
#endif
    strcat(file, font);
    strcat(file, ".pfb");
    error = FT_New_Face(library, file, 0, &face);
    if (error == FT_Err_Unknown_File_Format) {
      gks_perror("unknown file format: %s", file);
      return NULL;
    } else if (error) {
      gks_perror("could not open font file: %s", file);
      return NULL;
    }
    if (strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0) {
      strcpy(file, prefix);
#ifndef _WIN32
      strcat(file, "/fonts/");
#else
      strcat(file, "\\FONTS\\");
#endif
      strcat(file, font);
      strcat(file, suffix_type1);
      FT_Attach_File(face, file);
    }
    free(file);
    font_face_cache[textfont] = face;
  } else {
    face = font_face_cache[textfont];
  }

  num_glyphs = length;
  unicode_string = (FT_UInt *) malloc(length * sizeof(FT_UInt) + 1);
  if (textfont + 1 == 13) {
    symbol_to_unicode((FT_Bytes)text, unicode_string, num_glyphs);
  } else {
    utf_to_unicode((FT_Bytes)text, unicode_string, &num_glyphs);
  }

  textheight = nint(gkss->chh * windowwidth * 64 / caps[textfont]);
  error = FT_Set_Char_Size(face, nint(textheight * gkss->chxp), textheight,
                           72, 72);
  if (error) gks_perror("cannot set text height");

  if (gkss->chup[0] != 0.0 || gkss->chup[1] != 0.0) {
    angle = atan2f(gkss->chup[1], gkss->chup[0]) - M_PI / 2;
    rotation.xx = nint( cosf(angle) * 0x10000L);
    rotation.xy = nint(-sinf(angle) * 0x10000L);
    rotation.yx = nint( sinf(angle) * 0x10000L);
    rotation.yy = nint( cosf(angle) * 0x10000L);
    FT_Set_Transform(face, &rotation, NULL);
  } else {
    FT_Set_Transform(face, NULL, NULL);
  }

  spacing.x = spacing.y = 0;
  if (gkss->chsp != 0.0) {
    error = FT_Load_Glyph(face, FT_Get_Char_Index(face, ' '),
                          vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT);
    if (!error) {
      spacing.x = nint(face->glyph->advance.x * gkss->chsp);
      spacing.y = nint(face->glyph->advance.y * gkss->chsp);
    } else {
      gks_perror("cannot apply character spacing");
    }
  }

  bb.xMin = bb.yMin = LONG_MAX;
  bb.xMax = bb.yMax = LONG_MIN;
  pen.x = pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    bb.xMin = ft_min(bb.xMin, pen.x + bearing.x);
    bb.xMax = ft_max(bb.xMax, pen.x + bearing.x + 64*face->glyph->bitmap.width);
    bb.yMin = ft_min(bb.yMin, pen.y + bearing.y - 64*face->glyph->bitmap.rows);
    bb.yMax = ft_max(bb.yMax, pen.y + bearing.y);

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  *width  = (int)((bb.xMax - bb.xMin) / 64);
  *height = (int)((bb.yMax - bb.yMin) / 64);
  if (bb.xMax <= bb.xMin || bb.yMax <= bb.yMin) {
    gks_perror("invalid bitmap size");
    free(unicode_string);
    return NULL;
  }
  size = *width * *height;
  mono_bitmap = (FT_Byte *) safe_realloc(mono_bitmap, size);
  memset(mono_bitmap, 0, size);

  pen.x = 0;
  pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    bearing.x = bearing.y = 0;
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    pos_x = ( pen.x + bearing.x - bb.xMin) / 64;
    pos_y = (-pen.y - bearing.y + bb.yMax) / 64;
    ftbitmap = face->glyph->bitmap;
    for (j = 0; j < (unsigned int) ftbitmap.rows; j++) {
      for (k = 0; k < (unsigned int) ftbitmap.width; k++) {
        dx = k + pos_x;
        dy = j + pos_y;
        value = mono_bitmap[dy * *width + dx];
        value += ftbitmap.buffer[j * ftbitmap.pitch + k];
        if (value > 255) {
          value = 255;
        }
        mono_bitmap[dy * *width + dx] = value;
      }
    }

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  free(unicode_string);

  /* Alignment */
  if (direction == GKS_K_TEXT_PATH_DOWN) {
    pen.x += spacing.x;
    pen.y += spacing.y;
  } else {
    pen.x -= spacing.x;
    pen.y -= spacing.y;
  }

  align.x = align.y = 0;
  if (valign != GKS_K_TEXT_VALIGN_BASE) {
    align.y = nint(gkss->chh * windowwidth * 64);
    FT_Vector_Transform(&align, &rotation);
    if (valign == GKS_K_TEXT_VALIGN_HALF) {
      align.x = nint(0.5 * align.x);
      align.y = nint(0.5 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_TOP) {
      align.x = nint(1.2 * align.x);
      align.y = nint(1.2 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_BOTTOM) {
      align.x = nint(-0.2 * align.x);
      align.y = nint(-0.2 * align.y);
    }
  }

  if (!vertical && halign != GKS_K_TEXT_HALIGN_LEFT) {
    FT_Vector right;
    right.x = face->glyph->metrics.width + face->glyph->metrics.horiBearingX;
    right.y = 0;
    if (right.x != 0) {
      FT_Vector_Transform(&right, &rotation);
    }
    pen.x += right.x - face->glyph->advance.x;
    pen.y += right.y - face->glyph->advance.y;
    if (halign == GKS_K_TEXT_HALIGN_CENTER) {
      align.x += pen.x / 2;
      align.y += pen.y / 2;
    } else if (halign == GKS_K_TEXT_HALIGN_RIGHT) {
      align.x += pen.x;
      align.y += pen.y;
    }
  }

  *x += (bb.xMin - align.x) / 64;
  *y += (bb.yMin - align.y) / 64;
  return mono_bitmap;
}
	FreetypeFontProvider::FreetypeFontProvider(const FontProvider::Options& options): FontProvider(options)
	{
		if ( options.size.height < 1 )
		{
			throw std::runtime_error("[FreetypeFontProvider] Invalid size");
		}

		if ( options.mode == L"" || options.mode == L"normal" )
		{
			m_render_mode = FT_RENDER_MODE_NORMAL;
		}
		else if ( options.mode == L"monochrome" )
		{
			m_render_mode = FT_RENDER_MODE_MONO;
		}
		else if ( options.mode == L"lcd" )
		{
			m_render_mode = FT_RENDER_MODE_LCD;
		}
		else
		{
			throw std::runtime_error("[FreetypeFontProvider] Invalid font.mode");
		}

		if ( FT_Init_FreeType(&m_font_library) )
		{
			throw std::runtime_error("[FreetypeFontProvider] Can't initialize Freetype");
		}

		std::string filename_u8 = Encoding::UTF8.FromUCS2(options.name);
		if ( FT_New_Face(m_font_library, filename_u8.c_str(), 0, &m_font_face) )
		{
			Dispose();
			throw std::runtime_error("[FreetypeFontProvider] Can't load font from file");
		}

		int hres = 64;
		FT_Matrix matrix =
		{
			(int)((1.0/hres) * 0x10000L),
			(int)((0.0)      * 0x10000L),
			(int)((0.0)      * 0x10000L),
			(int)((1.0)      * 0x10000L)
		};

		if ( FT_Set_Char_Size(m_font_face, (uint32_t)(options.size.height*64), 0, 96*hres, 96) )
		{
			Dispose();
			throw std::runtime_error("[FreetypeFontProvider] Can't setup font");
		}

		FT_Set_Transform(m_font_face, &matrix, NULL);

		float yscale = m_font_face->size->metrics.y_scale / (float)(1 << 16);
		int height = std::ceil((m_font_face->bbox.yMax-m_font_face->bbox.yMin) * yscale / 64.0f);
		//int descender = std::floor(m_font_face->descender * yscale / 64.0f);
		//int ascender = std::ceil(m_font_face->ascender * yscale / 64.0f);

		auto get_metrics = [&](wchar_t code) -> FT_Glyph_Metrics
		{
			if ( FT_Load_Glyph(m_font_face, FT_Get_Char_Index(m_font_face, code), 0) )
			{
				throw std::runtime_error("[FreetypeFontProvider] Metrics error");
			}

			return m_font_face->glyph->metrics;
		};

		int width = 0;

		FT_Glyph_Metrics mDot = get_metrics(L'.'), mAt = get_metrics(L'@');
		if ( mDot.horiAdvance == mAt.horiAdvance )
		{
			// Monospace font
			width = std::ceil(mDot.horiAdvance / 64.0f);
		}
		else
		{
			// This is not a monospace font
			//throw std::runtime_error("[FreetypeFontProvider::ctor] This is not a monospace font");
			width = std::ceil(mAt.horiAdvance / 64.0f);
		}

		width = std::ceil(width/64.0);

		height = m_font_face->size->metrics.height >> 6;
		//descender = m_font_face->size->metrics.descender >> 6;

		m_cell_size = Size(width, height);
		m_glyph_size = Size(width, height);

		FT_Library_SetLcdFilter(m_font_library, FT_LCD_FILTER_DEFAULT);
		
		return;
	}
Beispiel #28
0
//-------------------------------------------------------------------------------------------------------
vector2d StringManager::_InternalGetStringSize( bool isScale, const vector2f& fontsize, const wstring& wstr )
{
    if (!m_isLoad)
    {
        DEBUGLOG("Font not loaded!!\n",1);
        return vector2d();
    }
    BCharList list;
    vector< pair<int,int> > LineElements;
    vector2d TexSize;//文本图片的吃村

    //第一步,读取全部的字体,找到最大的BeginY
    {
        int tempWidth = 0;
        int CharCount = 0; //每行文字的个数
        int MaxBeginY = 0; //最大的BeginY
        FT_Matrix scale;
        if( isScale )
        {   //这个缩放是在按像素比例来所放的,
            scale.xx = fontsize.m_x / m_FaceSize.m_x * 0x10000L;
            scale.xy = 0.0;
            scale.yy = fontsize.m_y / m_FaceSize.m_y * 0x10000L;
            scale.yx = 0.0;
        }

        for( int i = 0 ; i < wstr.size() ; )//制造全部的char
        {
            if( L'\n' != wstr[i] && L'#' != wstr[i] )
            {
                if( isScale )
                {
                    FT_Set_Transform( m_FT_Face, &scale, NULL );
                }
                CharCount++;
                BChar* pBChar = _LoadChar(wstr[i]);
                MaxBeginY = MaxBeginY < pBChar->m_nBeginY ? pBChar->m_nBeginY : MaxBeginY;
                tempWidth += pBChar->m_PixelSize.m_x;
                list.push_back(pBChar);
            }
            i++;//自增
            if( L'\n' == wstr[i] || L'#' == wstr[i] || wstr.size() == i )//如果是换行或者文本结束
            {
                TexSize.m_x = TexSize.m_x < tempWidth ? tempWidth : TexSize.m_x;
                LineElements.push_back(make_pair(CharCount, MaxBeginY));//每行文字的个数,这行最大的beginY
                CharCount = 0;
                MaxBeginY = 0;
                tempWidth = 0;
            }
        }

    }
    //第二部,找到每一行最大的高度,高度等于,最大BeginY减去当前字体的BeginY再加上当前字体的高度
    {
        int LineIndex = 0; //行数的索引
        int CharIndex = 0; //每行字的索引
        int maxHeight = 0; //每行最大高度
        for( BCharList::iterator it = list.begin();
                it != list.end();
                it ++)
        {
            CharIndex ++;
            int height = LineElements[LineIndex].second - (*it)->m_nBeginY + (*it)->m_PixelSize.m_y;
            maxHeight = maxHeight < height ? height : maxHeight;
            if( CharIndex == LineElements[LineIndex].first )//如果这行已经完了
            {
                TexSize.m_y = TexSize.m_y < maxHeight ? maxHeight : TexSize.m_y;
                maxHeight = 0;
                CharIndex = 0;
                LineIndex ++;
            }
            SAFE_DELETE( *it );
        }
    }
    //计算新的Y
    {
        int NewHeight = TexSize.m_y * 1.2;
        int SkyEarth = ( NewHeight - TexSize.m_y ) * 0.5 ;//上下预留0.2做留天留地
        TexSize.m_y = NewHeight;
        TexSize.m_y *= LineElements.size();
    }
    return TexSize;
}
Beispiel #29
0
// ------------------------------------------------- texture_font_load_face ---
int
texture_font_load_face( FT_Library * library,
                        const char * filename,
                        const float size,
                        FT_Face * face )
{
    assert( library );
    assert( filename );
    assert( size );

    size_t hres = 64;
    FT_Error error;
    FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L),
                         (int)((0.0)      * 0x10000L),
                         (int)((0.0)      * 0x10000L),
                         (int)((1.0)      * 0x10000L) };

    /* Initialize library */
    error = FT_Init_FreeType( library );
    if( error )
    {
        fprintf(stderr, "FT_Error (0x%02x) : %s\n",
                FT_Errors[error].code, FT_Errors[error].message);
        return 0;
    }

    /* Load face */
    error = FT_New_Face( *library, filename, 0, face );
    if( error )
    {
        fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                 __LINE__, FT_Errors[error].code, FT_Errors[error].message);
        FT_Done_FreeType( *library );
        return 0;
    }

    /* Select charmap */
    error = FT_Select_Charmap( *face, FT_ENCODING_UNICODE );
    if( error )
    {
        fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                 __LINE__, FT_Errors[error].code, FT_Errors[error].message );
        FT_Done_Face( *face );
        FT_Done_FreeType( *library );
        return 0;
    }

    /* Set char size */
    error = FT_Set_Char_Size( *face, (int)(size*64), 0, 72*hres, 72 );
    if( error )
    {
        fprintf( stderr, "FT_Error (line %d, code 0x%02x) : %s\n",
                 __LINE__, FT_Errors[error].code, FT_Errors[error].message );
        FT_Done_Face( *face );
        FT_Done_FreeType( *library );
        return 0;
    }

    /* Set transform matrix */
    FT_Set_Transform( *face, &matrix, NULL );

    return 1;
}
Beispiel #30
0
BString* StringManager::_InternalMakeString(bool isScale, const vector2f& fontsize, const Color& clr, const wstring& wstr)
{
    if (!m_isLoad)
    {
        DEBUGLOG("Font not loaded!!\n",1);
        return NULL;
    }
    BCharList list;
    vector< pair<int,int> > LineElements;
    vector2d TexSize;//文本图片的吃村

    //第一步,读取全部的字体,找到最大的BeginY
    {
        int tempWidth = 0;
        int CharCount = 0; //每行文字的个数
        int MaxBeginY = 0; //最大的BeginY
        FT_Matrix scale;
        if( isScale )
        {   //这个缩放是在按像素比例来所放的,
            scale.xx = fontsize.m_x / m_FaceSize.m_x * 0x10000L;
            scale.xy = 0.0;
            scale.yy = fontsize.m_y / m_FaceSize.m_y * 0x10000L;
            scale.yx = 0.0;
        }

        for( int i = 0 ; i < wstr.size() ; )//制造全部的char
        {
            if( L'\n' != wstr[i] && L'#' != wstr[i] )
            {
                if( isScale )
                {
                    FT_Set_Transform( m_FT_Face, &scale, NULL );
                }
                CharCount++;
                BChar* pBChar = _LoadChar(wstr[i]);
                MaxBeginY = MaxBeginY < pBChar->m_nBeginY ? pBChar->m_nBeginY : MaxBeginY;
                tempWidth += pBChar->m_PixelSize.m_x;
                list.push_back(pBChar);
            }
            i++;//自增
            if( L'\n' == wstr[i] || L'#' == wstr[i] || wstr.size() == i )//如果是换行或者文本结束
            {
                TexSize.m_x = TexSize.m_x < tempWidth ? tempWidth : TexSize.m_x;
                LineElements.push_back(make_pair(CharCount, MaxBeginY));//每行文字的个数,这行最大的beginY
                CharCount = 0;
                MaxBeginY = 0;
                tempWidth = 0;
            }
        }

    }
    //第二部,找到每一行最大的高度,高度等于,最大BeginY减去当前字体的BeginY再加上当前字体的高度
    {
        int LineIndex = 0; //行数的索引
        int CharIndex = 0; //每行字的索引
        int maxHeight = 0; //每行最大高度
        for( BCharList::iterator it = list.begin();
                it != list.end();
                it ++)
        {
            CharIndex ++;
            int height = LineElements[LineIndex].second - (*it)->m_nBeginY + (*it)->m_PixelSize.m_y;
            maxHeight = maxHeight < height ? height : maxHeight;
            if( CharIndex == LineElements[LineIndex].first )//如果这行已经完了
            {
                TexSize.m_y = TexSize.m_y < maxHeight ? maxHeight : TexSize.m_y;
                maxHeight = 0;
                CharIndex = 0;
                LineIndex ++;
            }
        }

    }
    //第三步,填充图像了
    vector2d orgiSize;//原始的内用尺寸
    BString* Result;
    int ResultHeight;//行高
    {
        int NewHeight = TexSize.m_y * 1.2;
        ResultHeight = NewHeight;
        int SkyEarth = ( NewHeight - TexSize.m_y ) * 0.5 ;//上下预留0.2做留天留地
        TexSize.m_y = NewHeight;
        int Height = TexSize.m_y;
        TexSize.m_y *= LineElements.size();
        //将TextSize改变之power of two
        orgiSize = TexSize;
        TexSize.m_x = PowerOfTwo( TexSize.m_x );
        TexSize.m_y = PowerOfTwo( TexSize.m_y );
        byte* pBuffer = NEW byte[ TexSize.m_x * TexSize.m_y ];
        int LineIndex = 0; //行数的索引
        int CharIndex = 0; //每行字的索引
        vector2d offset; //读取每一个字体放在新的buffer中的偏移
        memset(pBuffer,0,TexSize.m_x * TexSize.m_y );
        for ( BCharList::iterator it = list.begin();
                it != list.end();
                it++)
        {
            int horBeginPos = LineElements[LineIndex].second - (*it)->m_nBeginY + SkyEarth ; //在图片数组中绘制文本的其实竖直起始位置
            int horEndPos = horBeginPos + (*it)->m_PixelSize.m_y;//在图片数组中绘制文本的其实竖直起结束的位置
            FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)(*it)->m_pGlyph;
            for(int j=0; j  < Height ; j++) //根据图片的宽度,进行中线对其文本,竖着读第一个文字的像素
            {
                if( j < horBeginPos || j >= horEndPos || (*it)->m_isSpace ) //如果不在需要绘制的范围内
                {
                    continue;
                }
                for(int i=0; i < (*it)->m_PixelSize.m_x; i++)
                {
                    int index = (i + offset.m_x) + ( j + offset.m_y ) * TexSize.m_x;
                    //bite alpha = j >= horBeginPos && j < horEndPos && !(*it)->m_isSpace //当在绘制范围之内时,且不是空格的时候
                    //	? bitmap_glyph->bitmap.buffer[ i + (*it)->m_PixelSize.m_x* ( j - horBeginPos ) ] : 0;
                    byte alpha = bitmap_glyph->bitmap.buffer[ i + (*it)->m_PixelSize.m_x* ( j - horBeginPos ) ];
                    pBuffer[index] = alpha;
                }
            }
            offset.m_x += (*it)->m_PixelSize.m_x;//计算x位置的offset
            SAFE_DELETE(*it);//顺便就清理了
            CharIndex++;//读完一个
            if( CharIndex >= LineElements[LineIndex].first ) //如果这行已经读完了
            {
                offset.m_y += Height;
                offset.m_x = 0; //水平的偏移重置
                CharIndex = 0;
                LineIndex ++;
            }
        }
        Result = NEW BString( this, wstr, ResultHeight, fontsize, orgiSize, clr, this->_AllocBuffer() , TexSize, pBuffer);
        SAFE_DELETE_ARRAY(pBuffer);
        m_StringList.push_back(Result);
        Result->SetIterator( (++m_StringList.rbegin()).base() );
    }
    //DEBUGLOG("String size %d, %d\n", TextSize.m_x, TextSize.m_y);
    return Result;
}