Perhaps it is easier just to show you what I have - this is already functional 
and I can even switch COLRv1 palettes in ftgrid (screenshots the usual place). 
Basically it works the same ways as svg hooks: the preset slot hook calculates 
the bound boxes, while the render hook actually draws to the bitmap.

In this case, I have a FT_Load_Glyph_Extended() which calls FT_Load_Glyph(), 
but also call FT_Get_Color_Glyph_ClipBox_Extended(), which is a skia routine 
which does FT_Get_Color_Glyph_ClipBox() but also if that fails, tries to union 
all the layers to calculate a skia bound box. I should convert back to override 
the FT_Load_Glyph() bound values but haven't (yet).


Then I have a "FT_Glyph_To_Bitmap_Extended()" which also calls 
"FT_Glyph_To_Bitmap()", but then overwrite and draws to its bitmap with skia 
before returning. I'd like to not call "FT_Glyph_To_Bitmap()" but just do 
'FT_New_Glyph()' on my own, but that always crashes. why?

'...' and '...' are deleted parts too ugly that will hurt your eyes if you see 
them :-).  
#include "skia-colrv1-stub.h"
#include FT_COLOR_H
#include FT_BITMAP_H
#include "include/core/SkRect.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "freetype/internal/ftobjs.h"
#include "skia-src-ports-SkFontHost_FreeType_common_colrv1.h"

/* in skia-src-ports-SkFontHost_FreeType_colrv1.cpp */
SkRect FT_Get_Color_Glyph_ClipBox_Extended( FT_Face      fFace,
                                            FT_UInt      base_glyph,
                                            FT_ClipBox*  clip_box );

FT_Bool isCOLRv1(FT_Face   face,
                 FT_UInt   glyph_index) {
  if (FT_IS_SCALABLE(face)) {
    FT_OpaquePaint opaqueLayerPaint{nullptr, 1};
    if (FT_Get_Color_Glyph_Paint(face, glyph_index,
                                 FT_COLOR_INCLUDE_ROOT_TRANSFORM, &opaqueLayerPaint)) {
      return true;
    }
  }
  return false;
}

void skia_colr_set_current_palette( FT_Face   face,
                                    FT_UInt   palette_index ) {
  ... = ... palette_index;
}

FT_UShort skia_colr_get_current_palette( FT_Face   face ) {
  ... ;
}

FT_Error FT_Load_Glyph_Extended( FT_Face   face,
                                 FT_UInt   glyph_index,
                                 FT_Int32  load_flags ) {
  if ( isCOLRv1( face, glyph_index)
       && (load_flags & FT_LOAD_COLOR)
       ) {

    FT_ClipBox clipBox;
    SkRect bounds = FT_Get_Color_Glyph_ClipBox_Extended( face,
                                                         glyph_index,
                                                         &clipBox );
   ... keep bounds ...
  }

  FT_Error res = FT_Load_Glyph( face, glyph_index, load_flags );
  return res;
}

FT_Error FT_Glyph_To_Bitmap_Extended( FT_Glyph*         the_glyph,
                                      FT_Render_Mode    render_mode,
                                      const FT_Vector*  origin,
                                      FT_Bool           destroy ) {
   ...
  FT_Error res = FT_Glyph_To_Bitmap( the_glyph, render_mode, origin, destroy );

   ... retrieve bounds ...

  if ( face && bounds ) {
  FT_UInt  glyph_index = face->glyph->glyph_index;
    /* General variables. */
    int width  = ceil(bounds->right()) - floor(bounds->left()); //bounds.width();  // fRight minus fLeft
    int height = ceil(bounds->bottom()) - floor(bounds->top()); //bounds.height(); // fBottom minus fTop
    int x = floor(bounds->left());
    int y = floor(bounds->top());

    int size = width * height * 4;

    FT_Error   error;
    FT_Memory  memory  = lib->memory;
    FT_Glyph            gbitmap = NULL;

    if (isCOLRv1(face, glyph_index) && (FT_GLYPH_FORMAT_BITMAP == (*the_glyph)->format))
      {
        FT_BitmapGlyph            bitmap = (FT_BitmapGlyph)(*the_glyph);
        if ((bitmap->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) || (bitmap->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)) {

          SkBitmap dstBitmap;
          dstBitmap.setInfo(SkImageInfo::Make(bitmap->bitmap.width, bitmap->bitmap.rows,
                                              ((bitmap->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) ?
                                               kBGRA_8888_SkColorType : kGray_8_SkColorType),
                                              kPremul_SkAlphaType),
                            bitmap->bitmap.pitch);
          dstBitmap.setPixels(bitmap->bitmap.buffer);
          SkCanvas canvas(dstBitmap);
          canvas.clear(SK_ColorTRANSPARENT);
          canvas.translate( -x, -y );
          bool haveLayers =  skia_colrv1_start_glyph(&canvas,
                                                     face, glyph_index,
                                                     FT_COLOR_INCLUDE_ROOT_TRANSFORM);
          fprintf(stderr, "**bounds %d %d %d %d - SkRect Max\n",
                  x,
                  -y,
                  width,
                  height);
          fprintf(stderr, "**bounds %d %d %d %d - Not skia\n",
                  bitmap->left,
                  bitmap->top,
                  bitmap->bitmap.width,
                  bitmap->bitmap.rows);

        }
      }
     ...

    FT_New_Glyph( lib, FT_GLYPH_FORMAT_BITMAP, &gbitmap );
    if (FT_GLYPH_FORMAT_BITMAP == gbitmap->format)
      {
        FT_BitmapGlyph            bitmap2 = (FT_BitmapGlyph)gbitmap;
        //FT_MEM_ALLOC( bitmap2->bitmap.buffer, size ); // always crash - why?

      }
  }
  return res;
}

Reply via email to