Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef __LP64__
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <vector></vector>
Toshihiro Shimizu 890ddd
#include <iostream></iostream>
Toshihiro Shimizu 890ddd
#include <string></string>
Toshihiro Shimizu 890ddd
#include "tmathutil.h"
Toshihiro Shimizu 890ddd
#include "tdebugmessage.h"
Toshihiro Shimizu 890ddd
#include "tfont.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tcurves.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//----------------------------------------- structures
Shinya Kitaoka 120a6e
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef struct {
Shinya Kitaoka 120a6e
  Float32Point origin;  // The origin of the current glyph
Shinya Kitaoka 120a6e
  Boolean first;        // Keeps track of which segment is first in a glyph
Shinya Kitaoka 120a6e
  Float32Point
Shinya Kitaoka 120a6e
      current;  // The current pen position (used to filter degenerate cases)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  float adv;
Shinya Kitaoka 120a6e
  TVectorImageP m_image;
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} MyCurveCallbackData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef struct {
Shinya Kitaoka 120a6e
  ATSGlyphRef glyphID;  // The glyphID.  This is simply an index into a table in
Shinya Kitaoka 120a6e
                        // the font.
Shinya Kitaoka 120a6e
  Float32Point relativeOrigin;  // The origin of this glyph -- relative to the
Shinya Kitaoka 120a6e
                                // origin of the line.
Toshihiro Shimizu 890ddd
} MyGlyphRecord;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//-----------------------------------------
Shinya Kitaoka 38fd86
// callback---------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2,
Shinya Kitaoka 120a6e
                             void *callBackDataPtr) {
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
// Adjust the points according to the glyph origin
Shinya Kitaoka 120a6e
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
Shinya Kitaoka 120a6e
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
Shinya Kitaoka 120a6e
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
Shinya Kitaoka 120a6e
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
Shinya Kitaoka 120a6e
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (data->m_points.empty())
Shinya Kitaoka 120a6e
    data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
Shinya Kitaoka 120a6e
  // else
Shinya Kitaoka 120a6e
  // assert(isAlmostEqual(pt1 e back)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TThickPoint lastPoint = TThickPoint(pt2->x, pt2->y, 0);
Shinya Kitaoka 120a6e
  data->m_points.push_back((data->m_points.back() + lastPoint) * 0.5);
Shinya Kitaoka 120a6e
  data->m_points.push_back(lastPoint);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return noErr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OSStatus MyQuadraticCurveProc(const Float32Point *pt1,
Shinya Kitaoka 120a6e
                              const Float32Point *controlPt,
Shinya Kitaoka 120a6e
                              const Float32Point *pt2, void *callBackDataPtr) {
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
// Adjust the points according to the glyph origin
Shinya Kitaoka 120a6e
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
Shinya Kitaoka 120a6e
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
Shinya Kitaoka 120a6e
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
Shinya Kitaoka 120a6e
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
Shinya Kitaoka 120a6e
float cpx = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + controlPt->x;
Shinya Kitaoka 120a6e
float cpy = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + controlPt->y;
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (data->m_points.empty())
Shinya Kitaoka 120a6e
    data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
Shinya Kitaoka 120a6e
  // else
Shinya Kitaoka 120a6e
  // assert(isAlmostEqual(pt1 e back)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  data->m_points.push_back(TThickPoint(controlPt->x, controlPt->y, 0));
Shinya Kitaoka 120a6e
  data->m_points.push_back(TThickPoint(pt2->x, pt2->y, 0));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return noErr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OSStatus MyQuadraticNewPathProc(void *callBackDataPtr) {
Shinya Kitaoka 120a6e
  assert(((MyCurveCallbackData *)callBackDataPtr)->m_points.empty());
Shinya Kitaoka 120a6e
  return noErr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OSStatus MyQuadraticClosePathProc(void *callBackDataPtr) {
Shinya Kitaoka 120a6e
  MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(
Shinya Kitaoka 120a6e
      data->m_points.size() >= 3 &&
Shinya Kitaoka 120a6e
      data->m_points.size() &
Shinya Kitaoka 120a6e
          1);  // il numero di punti di controllo devono essere dispari e >= 3
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStroke *stroke = new TStroke(data->m_points);
Shinya Kitaoka 120a6e
  stroke->setSelfLoop(true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  data->m_points.clear();
Shinya Kitaoka 120a6e
  data->m_image->addStroke(stroke);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return noErr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void GetGlyphIDsAndPositions(ATSUTextLayout iLayout, UniCharArrayOffset iStart,
Shinya Kitaoka 120a6e
                             UniCharCount iLength,
Shinya Kitaoka 120a6e
                             MyGlyphRecord **oGlyphRecordArray,
Shinya Kitaoka 120a6e
                             ItemCount *oNumGlyphs) {
Shinya Kitaoka 120a6e
  // This block of code uses the new Direct Access APIs, which are only
Shinya Kitaoka 120a6e
  // available on Mac OS X 10.2 and later systems
Shinya Kitaoka 120a6e
  //
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ATSLayoutRecord *layoutRecords;
Shinya Kitaoka 120a6e
  ItemCount numRecords;
Shinya Kitaoka 120a6e
  Fixed *deltaYs;
Shinya Kitaoka 120a6e
  ItemCount numDeltaYs;
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  OSStatus status;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Get the arrays of glyph information
Shinya Kitaoka 120a6e
  status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
Shinya Kitaoka 120a6e
      iLayout, iStart, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
Shinya Kitaoka 120a6e
      (void **)&layoutRecords, &numRecords);
Shinya Kitaoka 120a6e
  assert(status == noErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
Shinya Kitaoka 120a6e
      iLayout, iStart, kATSUDirectDataBaselineDeltaFixedArray,
Shinya Kitaoka 120a6e
      (void **)&deltaYs, &numDeltaYs);
Shinya Kitaoka 120a6e
  assert(status == noErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build the array of MyGlyphRecords
Shinya Kitaoka 120a6e
  *oGlyphRecordArray =
Shinya Kitaoka 120a6e
      (MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord));
Shinya Kitaoka 120a6e
  *oNumGlyphs = numRecords;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < *oNumGlyphs; i++) {
Shinya Kitaoka 120a6e
    // Fill in the glyphID
Shinya Kitaoka 120a6e
    (*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Set up the relative origin of the glyph
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    // The real position is the x coordinate of the glyph, relative to the
Shinya Kitaoka 120a6e
    // beginning of the line
Shinya Kitaoka 120a6e
    // The baseline delta (deltaY), if any, is the y coordinate of the glyph,
Shinya Kitaoka 120a6e
    // relative to the baseline
Shinya Kitaoka 120a6e
    //
Shinya Kitaoka 120a6e
    (*oGlyphRecordArray)[i].relativeOrigin.x = Fix2X(layoutRecords[i].realPos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (deltaYs == NULL) {
Shinya Kitaoka 120a6e
      (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0 - Fix2X(deltaYs[i]);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Free the arrays of glyph information
Shinya Kitaoka 120a6e
  if (deltaYs != NULL) {
Shinya Kitaoka 120a6e
    status = ATSUDirectReleaseLayoutDataArrayPtr(
Shinya Kitaoka 120a6e
        NULL, kATSUDirectDataBaselineDeltaFixedArray, (void **)&deltaYs);
Shinya Kitaoka 120a6e
    assert(status == noErr);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  status = ATSUDirectReleaseLayoutDataArrayPtr(
Shinya Kitaoka 120a6e
      NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
Shinya Kitaoka 120a6e
      (void **)&layoutRecords);
Shinya Kitaoka 120a6e
  assert(status == noErr);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void drawQuadratics(ATSUTextLayout iLayout, ATSUStyle iStyle,
Shinya Kitaoka 120a6e
                    UniCharArrayOffset start, UniCharCount length,
Shinya Kitaoka 120a6e
                    MyCurveCallbackData &data) {
Shinya Kitaoka 120a6e
  // boh ----------------
Shinya Kitaoka 120a6e
  Fixed penX = 0;
Shinya Kitaoka 120a6e
  Fixed penY = 0;
Shinya Kitaoka 120a6e
  // -------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  MyGlyphRecord *glyphRecordArray;
Shinya Kitaoka 120a6e
  ItemCount numGlyphs;
Shinya Kitaoka 120a6e
  ATSQuadraticNewPathUPP newPathProc;
Shinya Kitaoka 120a6e
  ATSQuadraticLineUPP lineProc;
Shinya Kitaoka 120a6e
  ATSQuadraticCurveUPP curveProc;
Shinya Kitaoka 120a6e
  ATSQuadraticClosePathUPP closePathProc;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  OSStatus status;
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Create the Quadratic callbacks
Shinya Kitaoka 120a6e
  newPathProc   = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc);
Shinya Kitaoka 120a6e
  lineProc      = NewATSQuadraticLineUPP(MyQuadraticLineProc);
Shinya Kitaoka 120a6e
  curveProc     = NewATSQuadraticCurveUPP(MyQuadraticCurveProc);
Shinya Kitaoka 120a6e
  closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Get the array of glyph information
Shinya Kitaoka 120a6e
  GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray,
Shinya Kitaoka 120a6e
                          &numGlyphs);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Loop over all the glyphs
Shinya Kitaoka 120a6e
  for (i = 0; i < numGlyphs; i++) {
Shinya Kitaoka 120a6e
    // Set up the absolute origin of the glyph
Shinya Kitaoka 120a6e
    data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x;
Shinya Kitaoka 120a6e
    data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Reset state for quadratic drawing (the callbacks only do a MoveTo on the
Shinya Kitaoka 120a6e
    // very first segment)
Shinya Kitaoka 120a6e
    data.first = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // If this is a deleted glyph (-1), don't draw it.  Otherwise, go ahead.
Shinya Kitaoka 120a6e
    if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) {
Shinya Kitaoka 120a6e
      status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID,
Shinya Kitaoka 120a6e
                                          newPathProc, lineProc, curveProc,
Shinya Kitaoka 120a6e
                                          closePathProc, &data, &status);
Shinya Kitaoka 120a6e
      assert(status == noErr);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // Free the array of glyph information
Shinya Kitaoka 120a6e
  free(glyphRecordArray);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Dispose of the Quadratic callbacks
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DisposeATSQuadraticNewPathUPP(newPathProc);
Shinya Kitaoka 120a6e
  DisposeATSQuadraticLineUPP(lineProc);
Shinya Kitaoka 120a6e
  DisposeATSQuadraticCurveUPP(curveProc);
Shinya Kitaoka 120a6e
  DisposeATSQuadraticClosePathUPP(closePathProc);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct TFont::Impl {
Shinya Kitaoka 120a6e
  bool m_hasKerning;
Shinya Kitaoka 120a6e
  int m_hasVertical;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //  KerningPairs m_kerningPairs;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ATSUStyle m_style;
Shinya Kitaoka 120a6e
  ATSUFontID m_fontId;
Shinya Kitaoka 120a6e
  ATSUTextLayout m_layout;
Shinya Kitaoka 120a6e
  Fixed m_size;
Shinya Kitaoka 120a6e
  int m_ascender;
Shinya Kitaoka 120a6e
  int m_descender;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Impl(ATSUFontID fontId, int size);
Shinya Kitaoka 120a6e
  ~Impl();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // void getChar();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFont::TFont(ATSUFontID fontId, int size) { m_pimpl = new Impl(fontId, size); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFont::~TFont() { delete m_pimpl; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFont::Impl::Impl(ATSUFontID fontId, int size)
Shinya Kitaoka 120a6e
    : m_fontId(fontId), m_size(Long2Fix(size)) {
Shinya Kitaoka 120a6e
  OSStatus status;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  long response;
Shinya Kitaoka 120a6e
  status = Gestalt(gestaltATSUFeatures, &response);
Shinya Kitaoka 120a6e
  assert(response & gestaltATSUDirectAccess);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  status = ATSUCreateStyle(&m_style);
Shinya Kitaoka 120a6e
  assert(status == noErr);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ATSUAttributeTag tags[2];
Shinya Kitaoka 120a6e
  ByteCount sizes[2];
Shinya Kitaoka 120a6e
  ATSUAttributeValuePtr values[2];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tags[0]   = kATSUFontTag;
Shinya Kitaoka 120a6e
  sizes[0]  = sizeof(ATSUFontID);
Shinya Kitaoka 120a6e
  values[0] = &fontId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tags[1]   = kATSUSizeTag;
Shinya Kitaoka 120a6e
  sizes[1]  = sizeof(Fixed);
Shinya Kitaoka 120a6e
  values[1] = &m_size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  status = ATSUSetAttributes(m_style, 2, tags, sizes, values);
Shinya Kitaoka 120a6e
  // assert(status==noErr);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UniChar dummyStr[]  = {'H', 'e', 'l', 'l', 'o'};
Shinya Kitaoka 120a6e
  UniCharCount length = sizeof(dummyStr) / sizeof(UniChar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  status = ATSUCreateTextLayoutWithTextPtr(dummyStr, kATSUFromTextBeginning,
Shinya Kitaoka 120a6e
                                           kATSUToTextEnd, length, 1, &length,
Shinya Kitaoka 120a6e
                                           &m_style, &m_layout);
Shinya Kitaoka 120a6e
  // assert(status==noErr);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ATSTrapezoid glyphBounds;
Shinya Kitaoka 120a6e
  status =
Shinya Kitaoka 120a6e
      ATSUGetGlyphBounds(m_layout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd,
Shinya Kitaoka 120a6e
                         kATSUseFractionalOrigins, 1, &glyphBounds, NULL);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_ascender = -FixedToInt(glyphBounds.upperLeft.y);
Shinya Kitaoka 120a6e
  assert(m_ascender > 0);
Shinya Kitaoka 120a6e
  m_descender = -FixedToInt(glyphBounds.lowerLeft.y);
Shinya Kitaoka 120a6e
  assert(m_descender < 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFont::Impl::~Impl() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode,
Shinya Kitaoka 120a6e
                       wchar_t nextCharCode) const {
Shinya Kitaoka 120a6e
  OSStatus status;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UniChar subString[2];
Shinya Kitaoka 120a6e
  subString[0]        = charcode;
Shinya Kitaoka 120a6e
  subString[1]        = 0 /*nextCharCode*/;
Shinya Kitaoka 120a6e
  UniCharCount length = sizeof(subString) / sizeof(UniChar);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  status = ATSUCreateTextLayoutWithTextPtr(
Shinya Kitaoka 120a6e
      subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
Shinya Kitaoka 120a6e
      &(m_pimpl->m_style), &(m_pimpl->m_layout));
Shinya Kitaoka 120a6e
  assert(status == noErr);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  MyCurveCallbackData data;
Shinya Kitaoka 120a6e
  data.m_image = image;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  drawQuadratics(m_pimpl->m_layout, m_pimpl->m_style, kATSUFromTextBeginning,
Shinya Kitaoka 120a6e
                 kATSUToTextEnd, data);
Shinya Kitaoka 120a6e
  image->transform(TScale(1, -1));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  image->group(0, image->getStrokeCount());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return getDistance(charcode, nextCharCode);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void appDrawChar(TRasterGR8P &outImage, TFont::Impl *pimpl, wchar_t charcode) {
Shinya Kitaoka 120a6e
  OSStatus status;
Shinya Kitaoka 120a6e
  UniChar subString[2];
Shinya Kitaoka 120a6e
  subString[0]        = charcode;
Shinya Kitaoka 120a6e
  subString[1]        = 0;
Shinya Kitaoka 120a6e
  UniCharCount length = sizeof(subString) / sizeof(UniChar);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  status = ATSUCreateTextLayoutWithTextPtr(
Shinya Kitaoka 120a6e
      subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
Shinya Kitaoka 120a6e
      &(pimpl->m_style), &(pimpl->m_layout));
Shinya Kitaoka 120a6e
  assert(status == noErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ATSTrapezoid glyphBounds;
Shinya Kitaoka 120a6e
  status = ATSUGetGlyphBounds(pimpl->m_layout, 0, 0, kATSUFromTextBeginning,
Shinya Kitaoka 120a6e
                              kATSUToTextEnd, kATSUseFractionalOrigins, 1,
Shinya Kitaoka 120a6e
                              &glyphBounds, NULL);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int height =
Shinya Kitaoka 120a6e
      FixedToInt(glyphBounds.lowerLeft.y) - FixedToInt(glyphBounds.upperLeft.y);
Shinya Kitaoka 120a6e
  int width = tmax(FixedToInt(glyphBounds.lowerRight.x),
Shinya Kitaoka 120a6e
                   FixedToInt(glyphBounds.upperRight.x)) -
Shinya Kitaoka 120a6e
              tmin(FixedToInt(glyphBounds.lowerLeft.x),
Shinya Kitaoka 120a6e
                   FixedToInt(glyphBounds.upperLeft.x));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  outImage = TRasterGR8P(width, height);
Shinya Kitaoka 120a6e
  TPixelGR8 bgp;
Shinya Kitaoka 120a6e
  bgp.value = 255;
Shinya Kitaoka 120a6e
  outImage->fill(bgp);
Shinya Kitaoka 120a6e
  void *data = outImage->getRawData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CGColorSpaceRef grayColorSpace =
Shinya Kitaoka 120a6e
      CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
Shinya Kitaoka 120a6e
  CGContextRef gContext = CGBitmapContextCreate(
Shinya Kitaoka 120a6e
      data, width, height, 8, width, grayColorSpace, kCGImageAlphaNone);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(DEBUG) || defined(_DEBUG)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int bpc = CGBitmapContextGetBitsPerComponent(gContext);
Shinya Kitaoka 120a6e
  if (bpc != 8) std::cout << "BitsPerComponent: " << bpc << std::endl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int bpp = CGBitmapContextGetBitsPerPixel(gContext);
Shinya Kitaoka 120a6e
  if (bpp != 8) std::cout << "BitsPerPixel: " << bpp << std::endl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int bytesPerRow = CGBitmapContextGetBytesPerRow(gContext);
Shinya Kitaoka 120a6e
  int newWidth    = CGBitmapContextGetWidth(gContext);
Shinya Kitaoka 120a6e
  if (bytesPerRow != width || newWidth != width)
Shinya Kitaoka 120a6e
    std::cout << "BytesPerRow: " << bytesPerRow << " Old width= " << width
Shinya Kitaoka 120a6e
              << " New width= " << newWidth << std::endl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int newHeight = CGBitmapContextGetHeight(gContext);
Shinya Kitaoka 120a6e
  if (newHeight != height)
Shinya Kitaoka 120a6e
    std::cout << " Old height= " << height << " New height= " << newHeight
Shinya Kitaoka 120a6e
              << std::endl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(CGBitmapContextGetColorSpace(gContext) == grayColorSpace);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ATSUAttributeTag tags[1];
Shinya Kitaoka 120a6e
  ByteCount sizes[1];
Shinya Kitaoka 120a6e
  ATSUAttributeValuePtr values[1];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tags[0]   = kATSUCGContextTag;
Shinya Kitaoka 120a6e
  sizes[0]  = sizeof(CGContextRef);
Shinya Kitaoka 120a6e
  values[0] = &gContext;
Shinya Kitaoka 120a6e
  status    = ATSUSetLayoutControls(pimpl->m_layout, 1, tags, sizes, values);
Shinya Kitaoka 120a6e
  assert(status == noErr);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ATSUDrawText(pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, 0,
Shinya Kitaoka 120a6e
               glyphBounds.lowerLeft.y);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode,
Shinya Kitaoka 120a6e
                       wchar_t nextCharCode) const {
Shinya Kitaoka 120a6e
  appDrawChar(outImage, m_pimpl, charcode);
Shinya Kitaoka 120a6e
  outImage->yMirror();
Shinya Kitaoka 120a6e
  return getDistance(charcode, nextCharCode);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId,
Shinya Kitaoka 120a6e
                       wchar_t charcode, wchar_t nextCharCode) const {
Shinya Kitaoka 120a6e
  TRasterGR8P grayAppImage;
Shinya Kitaoka 120a6e
  appDrawChar(grayAppImage, m_pimpl, charcode);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = grayAppImage->getLx();
Shinya Kitaoka 120a6e
  int ly = grayAppImage->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  outImage = TRasterCM32P(lx, ly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(TPixelCM32::getMaxTone() == 255);
Shinya Kitaoka 120a6e
  TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone());
Shinya Kitaoka 120a6e
  grayAppImage->lock();
Shinya Kitaoka 120a6e
  outImage->lock();
Shinya Kitaoka 120a6e
  int ty = 0;
Shinya Kitaoka 120a6e
  for (int gy = ly - 1; gy >= 0; --gy, ++ty) {
Shinya Kitaoka 120a6e
    TPixelGR8 *srcPix  = grayAppImage->pixels(gy);
Shinya Kitaoka 120a6e
    TPixelCM32 *tarPix = outImage->pixels(ty);
Shinya Kitaoka 120a6e
    for (int x = 0; x < lx; ++x) {
Shinya Kitaoka 120a6e
      int tone = srcPix->value;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (tone == 255)
Shinya Kitaoka 120a6e
        *tarPix = bgColor;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        *tarPix = TPixelCM32(inkId, 0, tone);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ++srcPix;
Shinya Kitaoka 120a6e
      ++tarPix;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  grayAppImage->unlock();
Shinya Kitaoka 120a6e
  outImage->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return getDistance(charcode, nextCharCode);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const {
Shinya Kitaoka 120a6e
  OSStatus status;
Shinya Kitaoka 120a6e
  UniChar subString[2];
Shinya Kitaoka 120a6e
  subString[0]        = firstChar;
Shinya Kitaoka 120a6e
  subString[1]        = secondChar;
Shinya Kitaoka 120a6e
  UniCharCount length = sizeof(subString) / sizeof(UniChar);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  status = ATSUCreateTextLayoutWithTextPtr(
Shinya Kitaoka 120a6e
      subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
Shinya Kitaoka 120a6e
      &(m_pimpl->m_style), &(m_pimpl->m_layout));
Shinya Kitaoka 120a6e
  assert(status == noErr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  MyGlyphRecord *glyphRecordArray;
Shinya Kitaoka 120a6e
  ItemCount numGlyphs;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Get the array of glyph information
Shinya Kitaoka 120a6e
  GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning,
Shinya Kitaoka 120a6e
                          kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(numGlyphs >= 2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(glyphRecordArray[0].relativeOrigin.x == 0);
Shinya Kitaoka 120a6e
  int advance = (int)(glyphRecordArray[1].relativeOrigin.x -
Shinya Kitaoka 120a6e
                      glyphRecordArray[0].relativeOrigin.x);
Shinya Kitaoka 120a6e
  if (advance == 0) {
Shinya Kitaoka 120a6e
    subString[1] = 0;
Shinya Kitaoka 120a6e
    status       = ATSUCreateTextLayoutWithTextPtr(
Shinya Kitaoka 120a6e
        subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length,
Shinya Kitaoka 120a6e
        &(m_pimpl->m_style), &(m_pimpl->m_layout));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning,
Shinya Kitaoka 120a6e
                            kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
Shinya Kitaoka 120a6e
    advance = (int)(glyphRecordArray[1].relativeOrigin.x -
Shinya Kitaoka 120a6e
                    glyphRecordArray[0].relativeOrigin.x);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return TPoint(advance, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TFont::getMaxHeight() const {
Shinya Kitaoka 120a6e
  return m_pimpl->m_ascender - m_pimpl->m_descender;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TFont::getMaxWidth() const {
Shinya Kitaoka 120a6e
  assert(!"not implemented yet");
Shinya Kitaoka 120a6e
  return 100;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TFont::getLineAscender() const { return m_pimpl->m_ascender; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TFont::getLineDescender() const { return m_pimpl->m_descender; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TFont::hasKerning() const { return true; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TFont::hasVertical() const { return false; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <string></string>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::map<std::string, atsufontid=""> FontFamily;</std::string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::map<std::string, fontfamily=""> FamilyMap;</std::string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct TFontManager::Impl {
Shinya Kitaoka 120a6e
  FamilyMap m_families;
Shinya Kitaoka 120a6e
  bool m_loaded;
Shinya Kitaoka 120a6e
  ATSUFontID m_currentAtsuFontId;
Shinya Kitaoka 120a6e
  TFont *m_currentFont;
Shinya Kitaoka 120a6e
  wstring m_currentFamily;
Shinya Kitaoka 120a6e
  wstring m_currentTypeface;
Shinya Kitaoka 120a6e
  int m_size;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Impl()
Shinya Kitaoka 120a6e
      : m_currentAtsuFontId(0), m_currentFont(0), m_loaded(false), m_size(70) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool setFontName(ATSUFontID fontId, int platform, int script, int lang);
Shinya Kitaoka 120a6e
  bool addFont(ATSUFontID);
Shinya Kitaoka 120a6e
  void loadFontNames();
Shinya Kitaoka 120a6e
  bool setFont(std::wstring family, std::wstring style);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TFontManager::Impl::setFontName(ATSUFontID fontId, int platform,
Shinya Kitaoka 120a6e
                                     int script, int lang) {
Shinya Kitaoka 120a6e
  ByteCount oActualNameLength;
Shinya Kitaoka 120a6e
  ItemCount oFontCount;
Shinya Kitaoka 120a6e
  OSStatus status;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char *buffer  = 0;
Shinya Kitaoka 120a6e
  char *buffer2 = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // chiedo la lunhezza del Full Family Name per allocare il buffer
Shinya Kitaoka 120a6e
  status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang, 0, 0,
Shinya Kitaoka 120a6e
                            &oActualNameLength, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (status != noErr || oActualNameLength <= 1) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  buffer = new char[oActualNameLength + 1];
Shinya Kitaoka 120a6e
  // chiedo il Full Family Name
Shinya Kitaoka 120a6e
  status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang,
Shinya Kitaoka 120a6e
                            oActualNameLength, buffer, &oActualNameLength,
Shinya Kitaoka 120a6e
                            &oFontCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (status != noErr || oActualNameLength <= 1 || buffer[0] == '\0') {
Shinya Kitaoka 120a6e
    delete[] buffer;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  buffer[oActualNameLength] = '\0';
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // chiedo la lunhezza del Typeface Name per allocare il buffer
Shinya Kitaoka 120a6e
  status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang, 0,
Shinya Kitaoka 120a6e
                            0, &oActualNameLength, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (status != noErr || oActualNameLength <= 1) {
Shinya Kitaoka 120a6e
    delete[] buffer;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  buffer2 = new char[oActualNameLength + 1];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // chiedo il Typeface Name
Shinya Kitaoka 120a6e
  status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang,
Shinya Kitaoka 120a6e
                            oActualNameLength, buffer2, &oActualNameLength,
Shinya Kitaoka 120a6e
                            &oFontCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (status != noErr || oActualNameLength <= 1 || buffer2[0] == '\0') {
Shinya Kitaoka 120a6e
    delete[] buffer;
Shinya Kitaoka 120a6e
    delete[] buffer2;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    buffer2[oActualNameLength] = '\0';
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  string s_family(buffer);
Shinya Kitaoka 120a6e
  FontFamily &family      = m_families[s_family];
Shinya Kitaoka 120a6e
  family[string(buffer2)] = fontId;
Shinya Kitaoka 120a6e
  delete[] buffer;
Shinya Kitaoka 120a6e
  delete[] buffer2;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TFontManager::Impl::addFont(ATSUFontID fontId) {
Shinya Kitaoka 120a6e
  int platform, script, lang;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // per ottimizzare, ciclo solo sui valori
Shinya Kitaoka 120a6e
  // piu' comuni
Shinya Kitaoka 120a6e
  for (lang = -1; lang <= 0; lang++)
Shinya Kitaoka 120a6e
    for (platform = -1; platform <= 1; platform++)
Shinya Kitaoka 120a6e
      for (script = -1; script <= 0; script++)
Shinya Kitaoka 120a6e
        if (setFontName(fontId, platform, script, lang)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // poi li provo tutti
Shinya Kitaoka 120a6e
  for (lang = -1; lang <= 139; lang++)
Shinya Kitaoka 120a6e
    for (script = -1; script <= 32; script++)
Shinya Kitaoka 120a6e
      for (platform = -1; platform <= 4; platform++) {
Shinya Kitaoka 120a6e
        // escludo quelli nel tri-ciclo for precedente.
Shinya Kitaoka 120a6e
        // Purtoppo si deve fare cosi:
Shinya Kitaoka 120a6e
        // non si puo' fare partendo con indici piu' alti nei cicli for!
Shinya Kitaoka 120a6e
        if (-1 <= lang && lang <= 0 && -1 <= script && script <= 0 &&
Shinya Kitaoka 120a6e
            -1 <= platform && platform <= 1)
Shinya Kitaoka 120a6e
          continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        if (setFontName(fontId, platform, script, lang)) return true;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::Impl::loadFontNames() {
Shinya Kitaoka 120a6e
  if (m_loaded) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ItemCount oFontCount, fontCount;
Shinya Kitaoka 120a6e
  ATSUFontCount(&oFontCount);
Shinya Kitaoka 120a6e
  fontCount            = oFontCount;
Shinya Kitaoka 120a6e
  ATSUFontID *oFontIDs = new ATSUFontID[fontCount];
Shinya Kitaoka 120a6e
  ATSUGetFontIDs(oFontIDs, fontCount, &oFontCount);
Shinya Kitaoka 120a6e
  assert(fontCount == oFontCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (unsigned int i = 0; i < fontCount; i++) addFont(oFontIDs[i]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  delete[] oFontIDs;
Shinya Kitaoka 120a6e
  m_loaded = true;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TFontManager::Impl::setFont(std::wstring family, std::wstring typeface) {
Shinya Kitaoka 120a6e
  if (family == m_currentFamily &&
Shinya Kitaoka 120a6e
      (typeface == m_currentTypeface || typeface == L""))
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FamilyMap::iterator family_it = m_families.find(toString(family));
Shinya Kitaoka 120a6e
  if (family_it == m_families.end()) throw TFontCreationError();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_currentFamily = family;
Shinya Kitaoka 120a6e
  FontFamily::iterator style_it;
Shinya Kitaoka 120a6e
  if (typeface == L"") {
Shinya Kitaoka 120a6e
    style_it = ((*family_it).second).find(toString(m_currentTypeface));
Shinya Kitaoka 120a6e
    if (style_it == (*family_it).second.end())
Shinya Kitaoka 120a6e
      style_it = ((*family_it).second).begin();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    typeface = toWideString(style_it->first);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    style_it = ((*family_it).second).find(toString(typeface));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (style_it == (*family_it).second.end()) throw TFontCreationError();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_currentTypeface   = typeface;
Shinya Kitaoka 120a6e
  m_currentAtsuFontId = (*style_it).second;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFontManager::~TFontManager() { delete m_pimpl; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFontManager *TFontManager::instance() {
Shinya Kitaoka 120a6e
  static TFontManager theManager;
Shinya Kitaoka 120a6e
  return &theManager;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::loadFontNames() { m_pimpl->loadFontNames(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::setFamily(const wstring family) {
Shinya Kitaoka 120a6e
  bool changed = m_pimpl->setFont(family, L"");
Shinya Kitaoka 120a6e
  if (changed) {
Shinya Kitaoka 120a6e
    delete m_pimpl->m_currentFont;
Shinya Kitaoka 120a6e
    m_pimpl->m_currentFont =
Shinya Kitaoka 120a6e
        new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::setTypeface(const wstring typeface) {
Shinya Kitaoka 120a6e
  bool changed = m_pimpl->setFont(m_pimpl->m_currentFamily, typeface);
Shinya Kitaoka 120a6e
  if (changed) {
Shinya Kitaoka 120a6e
    delete m_pimpl->m_currentFont;
Shinya Kitaoka 120a6e
    m_pimpl->m_currentFont =
Shinya Kitaoka 120a6e
        new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::setSize(int size) {
Shinya Kitaoka 120a6e
  if (m_pimpl->m_size != size) {
Shinya Kitaoka 120a6e
    m_pimpl->m_size = size;
Shinya Kitaoka 120a6e
    delete m_pimpl->m_currentFont;
Shinya Kitaoka 120a6e
    m_pimpl->m_currentFont =
Shinya Kitaoka 120a6e
        new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
wstring TFontManager::getCurrentFamily() const {
Shinya Kitaoka 120a6e
  return m_pimpl->m_currentFamily;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
wstring TFontManager::getCurrentTypeface() const {
Shinya Kitaoka 120a6e
  return m_pimpl->m_currentTypeface;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFont *TFontManager::getCurrentFont() {
Shinya Kitaoka 120a6e
  if (m_pimpl->m_currentFont) return m_pimpl->m_currentFont;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_pimpl->m_currentFont) loadFontNames();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(!m_pimpl->m_families.empty());
Shinya Kitaoka 120a6e
  setFamily(toWideString(m_pimpl->m_families.begin()->first));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_pimpl->m_currentFont;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::getAllFamilies(vector<wstring> &families) const {</wstring>
Shinya Kitaoka 120a6e
  families.clear();
Shinya Kitaoka 120a6e
  families.reserve(m_pimpl->m_families.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FamilyMap::iterator it = m_pimpl->m_families.begin();
Shinya Kitaoka 120a6e
  for (; it != m_pimpl->m_families.end(); ++it) {
Shinya Kitaoka 120a6e
    families.push_back(toWideString(it->first));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TFontManager::getAllTypefaces(vector<wstring> &typefaces) const {</wstring>
Shinya Kitaoka 120a6e
  typefaces.clear();
Shinya Kitaoka 120a6e
  FamilyMap::iterator it_family =
Shinya Kitaoka 120a6e
      m_pimpl->m_families.find(toString(m_pimpl->m_currentFamily));
Shinya Kitaoka 120a6e
  if (it_family == m_pimpl->m_families.end()) return;
Shinya Kitaoka 120a6e
  FontFamily &typefaceSet = it_family->second;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  typefaces.reserve(typefaceSet.size());
Shinya Kitaoka 120a6e
  FontFamily::iterator it_typeface = typefaceSet.begin();
Shinya Kitaoka 120a6e
  for (; it_typeface != typefaceSet.end(); ++it_typeface) {
Shinya Kitaoka 120a6e
    typefaces.push_back(toWideString(it_typeface->first));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFontManager::setVertical(bool vertical) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif