text: /**************************************************************
   * 
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   * 
   *   http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   * 
   *************************************************************/
  
  
  
  // MARKER(update_precomp.py): autogen include statement, do not remove
  #include "precompiled_vcl.hxx"
  
  // We need this to enable namespace support in libgrengine headers.
  #define GR_NAMESPACE
  
  // Header files
  //
  // Standard Library
  #include <string>
  #include <cassert>
  #include "graphite_textsrc.hxx"
  #include <graphite_features.hxx>
  
  // class TextSourceAdaptor implementation.
  //
  TextSourceAdaptor::~TextSourceAdaptor()
  {
      delete mpFeatures;
  }
  
  gr::UtfType TextSourceAdaptor::utfEncodingForm() {
      return gr::kutf16;
  }
  
  
  size_t TextSourceAdaptor::getLength()
  {
      return maLayoutArgs.mnLength;
  }
  
  
  size_t  TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf32 *)
  {
      assert(false);
      return 0;
  }
  
  
  size_t  TextSourceAdaptor::fetch(gr::toffset offset, size_t char_count, gr::utf16 * char_buffer)
  {
    assert(char_buffer);
  
    size_t copy_count =  std::min(size_t(maLayoutArgs.mnLength), char_count);
    std::copy(maLayoutArgs.mpStr + offset, maLayoutArgs.mpStr + offset + copy_count, char_buffer);
  
    return copy_count;
  }
  
  
  size_t TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf8  *)
  {
      assert(false);
      return 0;
  }
  
  
  inline void TextSourceAdaptor::getCharProperties(const int nCharIdx, int & min, int & lim, size_t & depth)
  {
      maLayoutArgs.ResetPos();
      bool rtl = maLayoutArgs.mnFlags & SAL_LAYOUT_BIDI_RTL;
      for(depth = ((rtl)? 1:0); maLayoutArgs.maRuns.GetRun(&min, &lim, &rtl); maLayoutArgs.maRuns.NextRun())
      {
          if (min > nCharIdx)
              break;
          // Only increase the depth when a change of direction occurs.
          depth += int(rtl ^ bool(depth & 0x1));
          if (min <= nCharIdx && nCharIdx < lim)
              break;
      }
      // If there is no run for this position increment the depth, but don't
      // change if this is out of bounds context
      if (lim > 0 && nCharIdx >= lim && nCharIdx < maLayoutArgs.mnEndCharPos)
          depth++;
  }
  
  
  bool TextSourceAdaptor::getRightToLeft(gr::toffset nCharIdx)
  {
      size_t depth;
      int min, lim = 0;
      getCharProperties(nCharIdx, min, lim, depth);
      //printf("getRtl %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth & 0x1);
      return depth & 0x1;
  }
  
  
  unsigned int TextSourceAdaptor::getDirectionDepth(gr::toffset nCharIdx)
  {
      size_t depth;
      int min, lim;
      getCharProperties(nCharIdx, min, lim, depth);
      //printf("getDirectionDepth %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth);
      return depth;
  }
  
  
  float TextSourceAdaptor::getVerticalOffset(gr::toffset)
  {
      return 0.0f;    //TODO: Implement correctly
  }
  
  gr::isocode TextSourceAdaptor::getLanguage(gr::toffset)
  {
      if (mpFeatures && mpFeatures->hasLanguage())
          return mpFeatures->getLanguage();
      gr::isocode unknown = {{0,0,0,0}};
      return unknown;
  }
  
  ext_std::pair<gr::toffset, gr::toffset> TextSourceAdaptor::propertyRange(gr::toffset nCharIdx)
  {
  
      if (nCharIdx < unsigned(maLayoutArgs.mnMinCharPos))
          return ext_std::make_pair(0, maLayoutArgs.mnMinCharPos);
  
      if (nCharIdx < mnEnd)
          return ext_std::make_pair(maLayoutArgs.mnMinCharPos, mnEnd);
  
      return ext_std::make_pair(mnEnd, maLayoutArgs.mnLength);
  }
  
  size_t TextSourceAdaptor::getFontFeatures(gr::toffset, gr::FeatureSetting * settings)
  {
      if (mpFeatures) return mpFeatures->getFontFeatures(settings);
      return 0;
  }
  
  
  bool TextSourceAdaptor::sameSegment(gr::toffset char_idx1, gr::toffset char_idx2)
  {
      const ext_std::pair<gr::toffset, gr::toffset>
      range1 = propertyRange(char_idx1),
      range2 = propertyRange(char_idx2);
  
      return range1 == range2;
  }
  
  void TextSourceAdaptor::setFeatures(const grutils::GrFeatureParser * pFeatures)
  {
      mpFeatures = new grutils::GrFeatureParser(*pFeatures);
  }
  