1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326 |
- /* Copyright (C) 2003 Aladdin Enterprises. All rights reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied,
- modified or distributed except as expressly authorized under the terms
- of the license contained in the file LICENSE in this distribution.
-
- For more information about licensing, please refer to
- http://www.ghostscript.com/licensing/. For information on
- commercial licensing, go to http://www.artifex.com/licensing/ or
- contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- San Rafael, CA 94903, U.S.A., +1(415)492-9861.
- */
- /* $Id: ttinterp.c,v 1.18 2005/08/02 11:12:32 igor Exp $ */
- /* Changes after FreeType: cut out the TrueType instruction interpreter. */
- /* Patented algorithms are replaced with THROW_PATENTED. */
- /*******************************************************************
- *
- * ttinterp.c 2.3
- *
- * TrueType bytecode intepreter.
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- *
- * TODO:
- *
- * - Fix the non-square pixel case (or how to manage the CVT to
- * detect horizontal and vertical scaled FUnits ?)
- *
- *
- * Changes between 2.3 and 2.2:
- *
- * - added support for rotation, stretching, instruction control
- *
- * - added support for non-square pixels. However, this doesn't
- * work perfectly yet...
- *
- * Changes between 2.2 and 2.1:
- *
- * - a small bugfix in the Push opcodes
- *
- * Changes between 2.1 and 2.0:
- *
- * - created the TTExec component to take care of all execution
- * context management. The interpreter has now one single
- * function.
- *
- * - made some changes to support re-entrancy. The re-entrant
- * interpreter is smaller!
- *
- ******************************************************************/
- #include "ttmisc.h"
- #include "ttfoutl.h"
- #include "tttypes.h"
- #include "ttcalc.h"
- #include "ttinterp.h"
- #include "ttfinp.h"
- #ifdef DEBUG
- # define DBG_PAINT CUR.current_face->font->DebugRepaint(CUR.current_face->font);
- # define DBG_PRT_FUN CUR.current_face->font->DebugPrint
- # define DBG_PRT (void)(!DBG_PRT_FUN ? 0 : DBG_PRT_FUN(CUR.current_face->font
- # define DBG_PRINT(fmt) DBG_PRT, fmt))
- # define DBG_PRINT1(fmt, a) DBG_PRT, fmt, a))
- # define DBG_PRINT3(fmt, a, b, c) DBG_PRT, fmt, a, b, c))
- # define DBG_PRINT4(fmt, a, b, c, d) DBG_PRT, fmt, a, b, c, d))
- #else
- # define DBG_PRT_FUN NULL
- # define DBG_PAINT
- # define DBG_PRINT(fmt)
- # define DBG_PRINT1(fmt, a)
- # define DBG_PRINT3(fmt, a, b, c)
- # define DBG_PRINT4(fmt, a, b, c, d)
- #endif
- static int nInstrCount=0;
- /* There are two kinds of implementations there: */
- /* */
- /* a. static implementation: */
- /* */
- /* The current execution context is a static variable, */
- /* which fields are accessed directly by the interpreter */
- /* during execution. The context is named 'cur'. */
- /* */
- /* This version is non-reentrant, of course. */
- /* */
- /* */
- /* b. indirect implementation: */
- /* */
- /* The current execution context is passed to _each_ */
- /* function as its first argument, and each field is */
- /* thus accessed indirectly. */
- /* */
- /* This version is, however, fully re-entrant. */
- /* */
- /* */
- /* The idea is that an indirect implementation may be */
- /* slower to execute on the low-end processors that are */
- /* used in some systems (like 386s or even 486s). */
- /* */
- /* When the interpreter started, we had no idea of the */
- /* time that glyph hinting (i.e. executing instructions) */
- /* could take in the whole process of rendering a glyph, */
- /* and a 10 to 30% performance penalty on low-end systems */
- /* didn't seem much of a good idea. This question led us */
- /* to provide two distinct builds of the C version from */
- /* a single source, with the use of macros (again). */
- /* */
- /* Now that the engine is working (and working really */
- /* well!), it seems that the greatest time-consuming */
- /* factors are: file i/o, glyph loading, rasterizing and */
- /* _then_ glyph hinting! */
- /* */
- /* Tests performed with two versions of the 'fttimer' */
- /* program seem to indicate that hinting takes less than 5% */
- /* of the rendering process, which is dominated by glyph */
- /* loading and scan-line conversion by an high order of */
- /* magnitude. */
- /* */
- /* As a consequence, the indirect implementation is now the */
- /* default, as its performance costs can be considered */
- /* negligible in our context. Note, however, that we */
- /* kept the same source with macros because: */
- /* */
- /* - the code is kept very close in design to the */
- /* Pascal one used for development. */
- /* */
- /* - it's much more readable that way! */
- /* */
- /* - it's still open to later experimentation and tuning */
- #ifndef TT_STATIC_INTERPRETER /* indirect implementation */
- #define CUR (*exc) /* see ttobjs.h */
- #else /* static implementation */
- #define CUR cur
- static TExecution_Context cur; /* static exec. context variable */
- /* apparently, we have a _lot_ of direct indexing when accessing */
- /* the static 'cur', which makes the code bigger (due to all the */
- /* four bytes addresses). */
- #endif
- #define INS_ARG EXEC_OPS PStorage args /* see ttexec.h */
- #define SKIP_Code() SkipCode( EXEC_ARG )
- #define GET_ShortIns() GetShortIns( EXEC_ARG )
- #define COMPUTE_Funcs() Compute_Funcs( EXEC_ARG )
- #define NORMalize( x, y, v ) Normalize( EXEC_ARGS x, y, v )
- #define SET_SuperRound( scale, flags ) \
- SetSuperRound( EXEC_ARGS scale, flags )
- #define INS_Goto_CodeRange( range, ip ) \
- Ins_Goto_CodeRange( EXEC_ARGS range, ip )
- #define CUR_Func_project( x, y ) CUR.func_project( EXEC_ARGS x, y )
- #define CUR_Func_move( z, p, d ) CUR.func_move( EXEC_ARGS z, p, d )
- #define CUR_Func_dualproj( x, y ) CUR.func_dualproj( EXEC_ARGS x, y )
- #define CUR_Func_freeProj( x, y ) CUR.func_freeProj( EXEC_ARGS x, y )
- #define CUR_Func_round( d, c ) CUR.func_round( EXEC_ARGS d, c )
- #define CUR_Func_read_cvt( index ) \
- CUR.func_read_cvt( EXEC_ARGS index )
- #define CUR_Func_write_cvt( index, val ) \
- CUR.func_write_cvt( EXEC_ARGS index, val )
- #define CUR_Func_move_cvt( index, val ) \
- CUR.func_move_cvt( EXEC_ARGS index, val )
- #define CURRENT_Ratio() Current_Ratio( EXEC_ARG )
- #define CURRENT_Ppem() Current_Ppem( EXEC_ARG )
- #define CALC_Length() Calc_Length( EXEC_ARG )
- #define INS_SxVTL( a, b, c, d ) Ins_SxVTL( EXEC_ARGS a, b, c, d )
- #define COMPUTE_Point_Displacement( a, b, c, d ) \
- Compute_Point_Displacement( EXEC_ARGS a, b, c, d )
- #define MOVE_Zp2_Point( a, b, c, t ) Move_Zp2_Point( EXEC_ARGS a, b, c, t )
- #define CUR_Ppem() Cur_PPEM( EXEC_ARG )
- /* Instruction dispatch function, as used by the interpreter */
- typedef void (*TInstruction_Function)( INS_ARG );
- #define BOUNDS(x,n) ( x < 0 || x >= n )
- #ifndef ABS
- #define ABS(x) ( (x) < 0 ? -(x) : (x) )
- #endif
- /* The following macro is used to disable algorithms,
- which could cause Apple's patent infringement. */
- #define THROW_PATENTED longjmp(CUR.trap, TT_Err_Invalid_Engine)
- /*********************************************************************/
- /* */
- /* Before an opcode is executed, the interpreter verifies that */
- /* there are enough arguments on the stack, with the help of */
- /* the Pop_Push_Count table. */
- /* */
- /* For each opcode, the first column gives the number of arguments */
- /* that are popped from the stack; the second one gives the number */
- /* of those that are pushed in result. */
- /* */
- /* Note that for opcodes with a varying number of parameters, */
- /* either 0 or 1 arg is verified before execution, depending */
- /* on the nature of the instruction: */
- /* */
- /* - if the number of arguments is given by the bytecode */
- /* stream or the loop variable, 0 is chosen. */
- /* */
- /* - if the first argument is a count n that is followed */
- /* by arguments a1..an, then 1 is chosen. */
- /* */
- /*********************************************************************/
- static unsigned char Pop_Push_Count[512] =
- {
- /* opcodes are gathered in groups of 16 */
- /* please keep the spaces as they are */
- /* SVTCA y */ 0, 0,
- /* SVTCA x */ 0, 0,
- /* SPvTCA y */ 0, 0,
- /* SPvTCA x */ 0, 0,
- /* SFvTCA y */ 0, 0,
- /* SFvTCA x */ 0, 0,
- /* SPvTL // */ 2, 0,
- /* SPvTL + */ 2, 0,
- /* SFvTL // */ 2, 0,
- /* SFvTL + */ 2, 0,
- /* SPvFS */ 2, 0,
- /* SFvFS */ 2, 0,
- /* GPV */ 0, 2,
- /* GFV */ 0, 2,
- /* SFvTPv */ 0, 0,
- /* ISECT */ 5, 0,
- /* SRP0 */ 1, 0,
- /* SRP1 */ 1, 0,
- /* SRP2 */ 1, 0,
- /* SZP0 */ 1, 0,
- /* SZP1 */ 1, 0,
- /* SZP2 */ 1, 0,
- /* SZPS */ 1, 0,
- /* SLOOP */ 1, 0,
- /* RTG */ 0, 0,
- /* RTHG */ 0, 0,
- /* SMD */ 1, 0,
- /* ELSE */ 0, 0,
- /* JMPR */ 1, 0,
- /* SCvTCi */ 1, 0,
- /* SSwCi */ 1, 0,
- /* SSW */ 1, 0,
- /* DUP */ 1, 2,
- /* POP */ 1, 0,
- /* CLEAR */ 0, 0,
- /* SWAP */ 2, 2,
- /* DEPTH */ 0, 1,
- /* CINDEX */ 1, 1,
- /* MINDEX */ 1, 0,
- /* AlignPTS */ 2, 0,
- /* INS_$28 */ 0, 0,
- /* UTP */ 1, 0,
- /* LOOPCALL */ 2, 0,
- /* CALL */ 1, 0,
- /* FDEF */ 1, 0,
- /* ENDF */ 0, 0,
- /* MDAP[0] */ 1, 0,
- /* MDAP[1] */ 1, 0,
- /* IUP[0] */ 0, 0,
- /* IUP[1] */ 0, 0,
- /* SHP[0] */ 0, 0,
- /* SHP[1] */ 0, 0,
- /* SHC[0] */ 1, 0,
- /* SHC[1] */ 1, 0,
- /* SHZ[0] */ 1, 0,
- /* SHZ[1] */ 1, 0,
- /* SHPIX */ 1, 0,
- /* IP */ 0, 0,
- /* MSIRP[0] */ 2, 0,
- /* MSIRP[1] */ 2, 0,
- /* AlignRP */ 0, 0,
- /* RTDG */ 0, 0,
- /* MIAP[0] */ 2, 0,
- /* MIAP[1] */ 2, 0,
- /* NPushB */ 0, 0,
- /* NPushW */ 0, 0,
- /* WS */ 2, 0,
- /* RS */ 1, 1,
- /* WCvtP */ 2, 0,
- /* RCvt */ 1, 1,
- /* GC[0] */ 1, 1,
- /* GC[1] */ 1, 1,
- /* SCFS */ 2, 0,
- /* MD[0] */ 2, 1,
- /* MD[1] */ 2, 1,
- /* MPPEM */ 0, 1,
- /* MPS */ 0, 1,
- /* FlipON */ 0, 0,
- /* FlipOFF */ 0, 0,
- /* DEBUG */ 1, 0,
- /* LT */ 2, 1,
- /* LTEQ */ 2, 1,
- /* GT */ 2, 1,
- /* GTEQ */ 2, 1,
- /* EQ */ 2, 1,
- /* NEQ */ 2, 1,
- /* ODD */ 1, 1,
- /* EVEN */ 1, 1,
- /* IF */ 1, 0,
- /* EIF */ 0, 0,
- /* AND */ 2, 1,
- /* OR */ 2, 1,
- /* NOT */ 1, 1,
- /* DeltaP1 */ 1, 0,
- /* SDB */ 1, 0,
- /* SDS */ 1, 0,
- /* ADD */ 2, 1,
- /* SUB */ 2, 1,
- /* DIV */ 2, 1,
- /* MUL */ 2, 1,
- /* ABS */ 1, 1,
- /* NEG */ 1, 1,
- /* FLOOR */ 1, 1,
- /* CEILING */ 1, 1,
- /* ROUND[0] */ 1, 1,
- /* ROUND[1] */ 1, 1,
- /* ROUND[2] */ 1, 1,
- /* ROUND[3] */ 1, 1,
- /* NROUND[0] */ 1, 1,
- /* NROUND[1] */ 1, 1,
- /* NROUND[2] */ 1, 1,
- /* NROUND[3] */ 1, 1,
- /* WCvtF */ 2, 0,
- /* DeltaP2 */ 1, 0,
- /* DeltaP3 */ 1, 0,
- /* DeltaCn[0] */ 1, 0,
- /* DeltaCn[1] */ 1, 0,
- /* DeltaCn[2] */ 1, 0,
- /* SROUND */ 1, 0,
- /* S45Round */ 1, 0,
- /* JROT */ 2, 0,
- /* JROF */ 2, 0,
- /* ROFF */ 0, 0,
- /* INS_$7B */ 0, 0,
- /* RUTG */ 0, 0,
- /* RDTG */ 0, 0,
- /* SANGW */ 1, 0,
- /* AA */ 1, 0,
- /* FlipPT */ 0, 0,
- /* FlipRgON */ 2, 0,
- /* FlipRgOFF */ 2, 0,
- /* INS_$83 */ 0, 0,
- /* INS_$84 */ 0, 0,
- /* ScanCTRL */ 1, 0,
- /* SDVPTL[0] */ 2, 0,
- /* SDVPTL[1] */ 2, 0,
- /* GetINFO */ 1, 1,
- /* IDEF */ 1, 0,
- /* ROLL */ 3, 3,
- /* MAX */ 2, 1,
- /* MIN */ 2, 1,
- /* ScanTYPE */ 1, 0,
- /* InstCTRL */ 2, 0,
- /* INS_$8F */ 0, 0,
- /* INS_$90 */ 0, 0,
- /* INS_$91 */ 0, 0,
- /* INS_$92 */ 0, 0,
- /* INS_$93 */ 0, 0,
- /* INS_$94 */ 0, 0,
- /* INS_$95 */ 0, 0,
- /* INS_$96 */ 0, 0,
- /* INS_$97 */ 0, 0,
- /* INS_$98 */ 0, 0,
- /* INS_$99 */ 0, 0,
- /* INS_$9A */ 0, 0,
- /* INS_$9B */ 0, 0,
- /* INS_$9C */ 0, 0,
- /* INS_$9D */ 0, 0,
- /* INS_$9E */ 0, 0,
- /* INS_$9F */ 0, 0,
- /* INS_$A0 */ 0, 0,
- /* INS_$A1 */ 0, 0,
- /* INS_$A2 */ 0, 0,
- /* INS_$A3 */ 0, 0,
- /* INS_$A4 */ 0, 0,
- /* INS_$A5 */ 0, 0,
- /* INS_$A6 */ 0, 0,
- /* INS_$A7 */ 0, 0,
- /* INS_$A8 */ 0, 0,
- /* INS_$A9 */ 0, 0,
- /* INS_$AA */ 0, 0,
- /* INS_$AB */ 0, 0,
- /* INS_$AC */ 0, 0,
- /* INS_$AD */ 0, 0,
- /* INS_$AE */ 0, 0,
- /* INS_$AF */ 0, 0,
- /* PushB[0] */ 0, 1,
- /* PushB[1] */ 0, 2,
- /* PushB[2] */ 0, 3,
- /* PushB[3] */ 0, 4,
- /* PushB[4] */ 0, 5,
- /* PushB[5] */ 0, 6,
- /* PushB[6] */ 0, 7,
- /* PushB[7] */ 0, 8,
- /* PushW[0] */ 0, 1,
- /* PushW[1] */ 0, 2,
- /* PushW[2] */ 0, 3,
- /* PushW[3] */ 0, 4,
- /* PushW[4] */ 0, 5,
- /* PushW[5] */ 0, 6,
- /* PushW[6] */ 0, 7,
- /* PushW[7] */ 0, 8,
- /* MDRP[00] */ 1, 0,
- /* MDRP[01] */ 1, 0,
- /* MDRP[02] */ 1, 0,
- /* MDRP[03] */ 1, 0,
- /* MDRP[04] */ 1, 0,
- /* MDRP[05] */ 1, 0,
- /* MDRP[06] */ 1, 0,
- /* MDRP[07] */ 1, 0,
- /* MDRP[08] */ 1, 0,
- /* MDRP[09] */ 1, 0,
- /* MDRP[10] */ 1, 0,
- /* MDRP[11] */ 1, 0,
- /* MDRP[12] */ 1, 0,
- /* MDRP[13] */ 1, 0,
- /* MDRP[14] */ 1, 0,
- /* MDRP[15] */ 1, 0,
- /* MDRP[16] */ 1, 0,
- /* MDRP[17] */ 1, 0,
- /* MDRP[18] */ 1, 0,
- /* MDRP[19] */ 1, 0,
- /* MDRP[20] */ 1, 0,
- /* MDRP[21] */ 1, 0,
- /* MDRP[22] */ 1, 0,
- /* MDRP[23] */ 1, 0,
- /* MDRP[24] */ 1, 0,
- /* MDRP[25] */ 1, 0,
- /* MDRP[26] */ 1, 0,
- /* MDRP[27] */ 1, 0,
- /* MDRP[28] */ 1, 0,
- /* MDRP[29] */ 1, 0,
- /* MDRP[30] */ 1, 0,
- /* MDRP[31] */ 1, 0,
- /* MIRP[00] */ 2, 0,
- /* MIRP[01] */ 2, 0,
- /* MIRP[02] */ 2, 0,
- /* MIRP[03] */ 2, 0,
- /* MIRP[04] */ 2, 0,
- /* MIRP[05] */ 2, 0,
- /* MIRP[06] */ 2, 0,
- /* MIRP[07] */ 2, 0,
- /* MIRP[08] */ 2, 0,
- /* MIRP[09] */ 2, 0,
- /* MIRP[10] */ 2, 0,
- /* MIRP[11] */ 2, 0,
- /* MIRP[12] */ 2, 0,
- /* MIRP[13] */ 2, 0,
- /* MIRP[14] */ 2, 0,
- /* MIRP[15] */ 2, 0,
- /* MIRP[16] */ 2, 0,
- /* MIRP[17] */ 2, 0,
- /* MIRP[18] */ 2, 0,
- /* MIRP[19] */ 2, 0,
- /* MIRP[20] */ 2, 0,
- /* MIRP[21] */ 2, 0,
- /* MIRP[22] */ 2, 0,
- /* MIRP[23] */ 2, 0,
- /* MIRP[24] */ 2, 0,
- /* MIRP[25] */ 2, 0,
- /* MIRP[26] */ 2, 0,
- /* MIRP[27] */ 2, 0,
- /* MIRP[28] */ 2, 0,
- /* MIRP[29] */ 2, 0,
- /* MIRP[30] */ 2, 0,
- /* MIRP[31] */ 2, 0
- };
- /*******************************************************************
- *
- * Function : Norm
- *
- * Description : Returns the norm (length) of a vector.
- *
- * Input : X, Y vector
- *
- * Output : Returns length in F26dot6.
- *
- *****************************************************************/
- static TT_F26Dot6 Norm( TT_F26Dot6 X, TT_F26Dot6 Y )
- {
- Int64 T1, T2;
- MUL_64( X, X, T1 );
- MUL_64( Y, Y, T2 );
- ADD_64( T1, T2, T1 );
- return (TT_F26Dot6)SQRT_64( T1 );
- }
- /*******************************************************************
- *
- * Function : FUnits_To_Pixels
- *
- * Description : Scale a distance in FUnits to pixel coordinates.
- *
- * Input : Distance in FUnits
- *
- * Output : Distance in 26.6 format.
- *
- *****************************************************************/
- static TT_F26Dot6 FUnits_To_Pixels( EXEC_OPS Int distance )
- {
- return MulDiv_Round( distance,
- CUR.metrics.scale1,
- CUR.metrics.scale2 );
- }
- /*******************************************************************
- *
- * Function : Current_Ratio
- *
- * Description : Return the current aspect ratio scaling factor
- * depending on the projection vector's state and
- * device resolutions.
- *
- * Input : None
- *
- * Output : Aspect ratio in 16.16 format, always <= 1.0 .
- *
- *****************************************************************/
- static Long Current_Ratio( EXEC_OP )
- {
- if ( CUR.metrics.ratio )
- return CUR.metrics.ratio;
- if ( CUR.GS.projVector.y == 0 )
- CUR.metrics.ratio = CUR.metrics.x_ratio;
- else if ( CUR.GS.projVector.x == 0 )
- CUR.metrics.ratio = CUR.metrics.y_ratio;
- else
- {
- Long x, y;
- x = MulDiv_Round( CUR.GS.projVector.x, CUR.metrics.x_ratio, 0x4000 );
- y = MulDiv_Round( CUR.GS.projVector.y, CUR.metrics.y_ratio, 0x4000 );
- CUR.metrics.ratio = Norm( x, y );
- }
- return CUR.metrics.ratio;
- }
- static Int Current_Ppem( EXEC_OP )
- {
- return MulDiv_Round( CUR.metrics.ppem, CURRENT_Ratio(), 0x10000 );
- }
- static TT_F26Dot6 Read_CVT( EXEC_OPS Int index )
- {
- return CUR.cvt[index];
- }
- static TT_F26Dot6 Read_CVT_Stretched( EXEC_OPS Int index )
- {
- return MulDiv_Round( CUR.cvt[index], CURRENT_Ratio(), 0x10000 );
- }
- static void Write_CVT( EXEC_OPS Int index, TT_F26Dot6 value )
- {
- int ov=CUR.cvt[index];
- CUR.cvt[index] = value;
- DBG_PRINT3(" cvt[%d]%d:=%d", index, ov, CUR.cvt[index]);
- }
- static void Write_CVT_Stretched( EXEC_OPS Int index, TT_F26Dot6 value )
- {
- int ov=CUR.cvt[index];
- CUR.cvt[index] = MulDiv_Round( value, 0x10000, CURRENT_Ratio() );
- DBG_PRINT3(" cvt[%d]%d:=%d", index, ov, CUR.cvt[index]);
- }
- static void Move_CVT( EXEC_OPS Int index, TT_F26Dot6 value )
- {
- int ov=CUR.cvt[index];
- CUR.cvt[index] += value;
- DBG_PRINT3(" cvt[%d]%d:=%d", index, ov, CUR.cvt[index]);
- }
- static void Move_CVT_Stretched( EXEC_OPS Int index, TT_F26Dot6 value )
- {
- int ov=CUR.cvt[index];
- CUR.cvt[index] += MulDiv_Round( value, 0x10000, CURRENT_Ratio() );
- DBG_PRINT3(" cvt[%d]%d:=%d", index, ov, CUR.cvt[index]);
- }
- /******************************************************************
- *
- * Function : Calc_Length
- *
- * Description : Computes the length in bytes of current opcode.
- *
- *****************************************************************/
- static Bool Calc_Length( EXEC_OP )
- {
- CUR.opcode = CUR.code[CUR.IP];
- switch ( CUR.opcode )
- {
- case 0x40:
- if ( CUR.IP + 1 >= CUR.codeSize )
- return FAILURE;
- CUR.length = CUR.code[CUR.IP + 1] + 2;
- break;
- case 0x41:
- if ( CUR.IP + 1 >= CUR.codeSize )
- return FAILURE;
- CUR.length = CUR.code[CUR.IP + 1] * 2 + 2;
- break;
- case 0xB0:
- case 0xB1:
- case 0xB2:
- case 0xB3:
- case 0xB4:
- case 0xB5:
- case 0xB6:
- case 0xB7:
- CUR.length = CUR.opcode - 0xB0 + 2;
- break;
- case 0xB8:
- case 0xB9:
- case 0xBA:
- case 0xBB:
- case 0xBC:
- case 0xBD:
- case 0xBE:
- case 0xBF:
- CUR.length = (CUR.opcode - 0xB8) * 2 + 3;
- break;
- default:
- CUR.length = 1;
- break;
- }
- /* make sure result is in range */
- if ( CUR.IP + CUR.length > CUR.codeSize )
- return FAILURE;
- return SUCCESS;
- }
- /*******************************************************************
- *
- * Function : GetShortIns
- *
- * Description : Returns a short integer taken from the instruction
- * stream at address IP.
- *
- * Input : None
- *
- * Output : Short read at Code^[IP..IP+1]
- *
- * Notes : This one could become a Macro in the C version.
- *
- *****************************************************************/
- static Short GetShortIns( EXEC_OP )
- {
- /* Reading a byte stream so there is no endianess (DaveP) */
- CUR.IP += 2;
- return ( CUR.code[CUR.IP-2] << 8) +
- CUR.code[CUR.IP-1];
- }
- /*******************************************************************
- *
- * Function : Ins_Goto_CodeRange
- *
- * Description : Goes to a certain code range in the instruction
- * stream.
- *
- *
- * Input : aRange
- * aIP
- *
- * Output : SUCCESS or FAILURE.
- *
- *****************************************************************/
- static Bool Ins_Goto_CodeRange( EXEC_OPS Int aRange, Int aIP )
- {
- TCodeRange* WITH;
- if ( aRange < 1 || aRange > 3 )
- {
- CUR.error = TT_Err_Bad_Argument;
- return FAILURE;
- }
- WITH = &CUR.codeRangeTable[aRange - 1];
- if ( WITH->Base == NULL ) /* invalid coderange */
- {
- CUR.error = TT_Err_Invalid_CodeRange;
- return FAILURE;
- }
- /* NOTE: Because the last instruction of a program may be a CALL */
- /* which will return to the first byte *after* the code */
- /* range, we test for AIP <= Size, instead of AIP < Size. */
- if ( aIP > WITH->Size )
- {
- CUR.error = TT_Err_Code_Overflow;
- return FAILURE;
- }
- CUR.code = WITH->Base;
- CUR.codeSize = WITH->Size;
- CUR.IP = aIP;
- CUR.curRange = aRange;
- return SUCCESS;
- }
- /*******************************************************************
- *
- * Function : Direct_Move
- *
- * Description : Moves a point by a given distance along the
- * freedom vector.
- *
- * Input : Vx, Vy point coordinates to move
- * touch touch flag to modify
- * distance
- *
- * Output : None
- *
- *****************************************************************/
- static void Direct_Move( EXEC_OPS PGlyph_Zone zone,
- Int point,
- TT_F26Dot6 distance )
- {
- TT_F26Dot6 v;
- v = CUR.GS.freeVector.x;
- if ( v != 0 )
- {
- zone->cur_x[point] += MulDiv_Round( distance,
- v * 0x10000L,
- CUR.F_dot_P );
- zone->touch[point] |= TT_Flag_Touched_X;
- }
- v = CUR.GS.freeVector.y;
- if ( v != 0 )
- {
- zone->cur_y[point] += MulDiv_Round( distance,
- v * 0x10000L,
- CUR.F_dot_P );
- zone->touch[point] |= TT_Flag_Touched_Y;
- }
- }
- /******************************************************************/
- /* */
- /* The following versions are used whenever both vectors are both */
- /* along one of the coordinate unit vectors, i.e. in 90% cases. */
- /* */
- /******************************************************************/
- /*******************************************************************
- * Direct_Move_X
- *
- *******************************************************************/
- static void Direct_Move_X( EXEC_OPS PGlyph_Zone zone,
- Int point,
- TT_F26Dot6 distance )
- { (void)exc;
- zone->cur_x[point] += distance;
- zone->touch[point] |= TT_Flag_Touched_X;
- }
- /*******************************************************************
- * Direct_Move_Y
- *
- *******************************************************************/
- static void Direct_Move_Y( EXEC_OPS PGlyph_Zone zone,
- Int point,
- TT_F26Dot6 distance )
- { (void)exc;
- zone->cur_y[point] += distance;
- zone->touch[point] |= TT_Flag_Touched_Y;
- }
- /*******************************************************************
- *
- * Function : Round_None
- *
- * Description : Does not round, but adds engine compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : rounded distance.
- *
- * NOTE : The spec says very few about the relationship between
- * rounding and engine compensation. However, it seems
- * from the description of super round that we should
- * should add the compensation before rounding.
- *
- ******************************************************************/
- static TT_F26Dot6 Round_None( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = distance + compensation;
- if ( val < 0 )
- val = 0;
- }
- else {
- val = distance - compensation;
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_To_Grid
- *
- * Description : Rounds value to grid after adding engine
- * compensation
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_To_Grid( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = (distance + compensation + 32) & (-64);
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -( (compensation - distance + 32) & (-64) );
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_To_Half_Grid
- *
- * Description : Rounds value to half grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_To_Half_Grid( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = ((distance + compensation) & (-64)) + 32;
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -( ((compensation - distance) & (-64)) + 32 );
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_Down_To_Grid
- *
- * Description : Rounds value down to grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_Down_To_Grid( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = (distance + compensation) & (-64);
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -( (compensation - distance) & (-64) );
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_Up_To_Grid
- *
- * Description : Rounds value up to grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_Up_To_Grid( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = (distance + compensation + 63) & (-64);
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -( (compensation - distance + 63) & (-64) );
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_To_Double_Grid
- *
- * Description : Rounds value to double grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_To_Double_Grid( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- (void)exc;
- if ( distance >= 0 )
- {
- val = (distance + compensation + 16) & (-32);
- if ( val < 0 )
- val = 0;
- }
- else
- {
- val = -( (compensation - distance + 16) & (-32) );
- if ( val > 0 )
- val = 0;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_Super
- *
- * Description : Super-rounds value to grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- * NOTE : The spec says very few about the relationship between
- * rounding and engine compensation. However, it seems
- * from the description of super round that we should
- * should add the compensation before rounding.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_Super( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- if ( distance >= 0 )
- {
- val = (distance - CUR.phase + CUR.threshold + compensation) &
- (-CUR.period);
- if ( val < 0 )
- val = 0;
- val += CUR.phase;
- }
- else
- {
- val = -( (CUR.threshold - CUR.phase - distance + compensation) &
- (-CUR.period) );
- if ( val > 0 )
- val = 0;
- val -= CUR.phase;
- }
- return val;
- }
- /*******************************************************************
- *
- * Function : Round_Super_45
- *
- * Description : Super-rounds value to grid after adding engine
- * compensation.
- *
- * Input : distance : distance to round
- * compensation : engine compensation
- *
- * Output : Rounded distance.
- *
- * NOTE : There is a separate function for Round_Super_45 as we
- * may need a greater precision.
- *
- *****************************************************************/
- static TT_F26Dot6 Round_Super_45( EXEC_OPS TT_F26Dot6 distance,
- TT_F26Dot6 compensation )
- {
- TT_F26Dot6 val;
- if ( distance >= 0 )
- {
- val = ( (distance - CUR.phase + CUR.threshold + compensation) /
- CUR.period ) * CUR.period;
- if ( val < 0 )
- val = 0;
- val += CUR.phase;
- }
- else
- {
- val = -( ( (CUR.threshold - CUR.phase - distance + compensation) /
- CUR.period ) * CUR.period );
- if ( val > 0 )
- val = 0;
- val -= CUR.phase;
- }
- return val;
- }
- /*******************************************************************
- * Compute_Round
- *
- *****************************************************************/
- static void Compute_Round( EXEC_OPS Byte round_mode )
- {
- switch ( round_mode )
- {
- case TT_Round_Off:
- CUR.func_round = (TRound_Function)Round_None;
- break;
- case TT_Round_To_Grid:
- CUR.func_round = (TRound_Function)Round_To_Grid;
- break;
- case TT_Round_Up_To_Grid:
- CUR.func_round = (TRound_Function)Round_Up_To_Grid;
- break;
- case TT_Round_Down_To_Grid:
- CUR.func_round = (TRound_Function)Round_Down_To_Grid;
- break;
- case TT_Round_To_Half_Grid:
- CUR.func_round = (TRound_Function)Round_To_Half_Grid;
- break;
- case TT_Round_To_Double_Grid:
- CUR.func_round = (TRound_Function)Round_To_Double_Grid;
- break;
- case TT_Round_Super:
- CUR.func_round = (TRound_Function)Round_Super;
- break;
- case TT_Round_Super_45:
- CUR.func_round = (TRound_Function)Round_Super_45;
- break;
- }
- }
- /*******************************************************************
- *
- * Function : SetSuperRound
- *
- * Description : Sets Super Round parameters.
- *
- * Input : GridPeriod Grid period
- * OpCode SROUND opcode
- *
- * Output : None.
- *
- *****************************************************************/
- static void SetSuperRound( EXEC_OPS TT_F26Dot6 GridPeriod,
- Long selector )
- {
- switch ( selector & 0xC0 )
- {
- case 0:
- CUR.period = GridPeriod / 2;
- break;
- case 0x40:
- CUR.period = GridPeriod;
- break;
- case 0x80:
- CUR.period = GridPeriod * 2;
- break;
- /* This opcode is reserved, but... */
- case 0xC0:
- CUR.period = GridPeriod;
- break;
- }
- switch ( selector & 0x30 )
- {
- case 0:
- CUR.phase = 0;
- break;
- case 0x10:
- CUR.phase = CUR.period / 4;
- break;
- case 0x20:
- CUR.phase = CUR.period / 2;
- break;
- case 0x30:
- CUR.phase = GridPeriod * 3 / 4;
- break;
- }
- if ( (selector & 0x0F) == 0 )
- CUR.threshold = CUR.period - 1;
- else
- CUR.threshold = ( (Int)(selector & 0x0F) - 4L ) * CUR.period / 8;
- CUR.period /= 256;
- CUR.phase /= 256;
- CUR.threshold /= 256;
- }
- /*******************************************************************
- *
- * Function : Project
- *
- * Description : Computes the projection of (Vx,Vy) along the
- * current projection vector.
- *
- * Input : Vx, Vy input vector
- *
- * Output : Returns distance in F26dot6.
- *
- *****************************************************************/
- static TT_F26Dot6 Project( EXEC_OPS TT_F26Dot6 Vx, TT_F26Dot6 Vy )
- {
- THROW_PATENTED;
- return 0;
- }
- /*******************************************************************
- *
- * Function : Dual_Project
- *
- * Description : Computes the projection of (Vx,Vy) along the
- * current dual vector.
- *
- * Input : Vx, Vy input vector
- *
- * Output : Returns distance in F26dot6.
- *
- *****************************************************************/
- static TT_F26Dot6 Dual_Project( EXEC_OPS TT_F26Dot6 Vx, TT_F26Dot6 Vy )
- {
- THROW_PATENTED;
- return 0;
- }
- /*******************************************************************
- *
- * Function : Free_Project
- *
- * Description : Computes the projection of (Vx,Vy) along the
- * current freedom vector.
- *
- * Input : Vx, Vy input vector
- *
- * Output : Returns distance in F26dot6.
- *
- *****************************************************************/
- static TT_F26Dot6 Free_Project( EXEC_OPS TT_F26Dot6 Vx, TT_F26Dot6 Vy )
- {
- THROW_PATENTED;
- return 0;
- }
- /*******************************************************************
- *
- * Function : Project_x
- *
- * Input : Vx, Vy input vector
- *
- * Output : Returns Vx.
- *
- * Note : Used as a dummy function.
- *
- *****************************************************************/
- static TT_F26Dot6 Project_x( EXEC_OPS TT_F26Dot6 Vx, TT_F26Dot6 Vy )
- { (void)exc; (void)Vy;
- return Vx;
- }
- /*******************************************************************
- *
- * Function : Project_y
- *
- * Input : Vx, Vy input vector
- *
- * Output : Returns Vy.
- *
- * Note : Used as a dummy function.
- *
- *****************************************************************/
- static TT_F26Dot6 Project_y( EXEC_OPS TT_F26Dot6 Vx, TT_F26Dot6 Vy )
- { (void)exc; (void)Vx;
- return Vy;
- }
- /*******************************************************************
- *
- * Function : Compute_Funcs
- *
- * Description : Computes the projections and movement function
- * pointers according to the current graphics state.
- *
- * Input : None
- *
- *****************************************************************/
- static void Compute_Funcs( EXEC_OP )
- {
- if ( CUR.GS.freeVector.x == 0x4000 )
- {
- CUR.func_freeProj = (TProject_Function)Project_x;
- CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;
- }
- else
- {
- if ( CUR.GS.freeVector.y == 0x4000 )
- {
- CUR.func_freeProj = (TProject_Function)Project_y;
- CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;
- }
- else
- {
- CUR.func_move = (TMove_Function)Direct_Move;
- CUR.func_freeProj = (TProject_Function)Free_Project;
- CUR.F_dot_P = (Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
- (Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
- }
- }
- CUR.cached_metrics = FALSE;
- if ( CUR.GS.projVector.x == 0x4000 )
- CUR.func_project = (TProject_Function)Project_x;
- else
- {
- if ( CUR.GS.projVector.y == 0x4000 )
- CUR.func_project = (TProject_Function)Project_y;
- else
- CUR.func_project = (TProject_Function)Project;
- }
- if ( CUR.GS.dualVector.x == 0x4000 )
- CUR.func_dualproj = (TProject_Function)Project_x;
- else
- {
- if ( CUR.GS.dualVector.y == 0x4000 )
- CUR.func_dualproj = (TProject_Function)Project_y;
- else
- CUR.func_dualproj = (TProject_Function)Dual_Project;
- }
- CUR.func_move = (TMove_Function)Direct_Move;
- if ( CUR.F_dot_P == 0x40000000L )
- {
- if ( CUR.GS.freeVector.x == 0x4000 )
- CUR.func_move = (TMove_Function)Direct_Move_X;
- else
- {
- if ( CUR.GS.freeVector.y == 0x4000 )
- CUR.func_move = (TMove_Function)Direct_Move_Y;
- }
- }
- /* at small sizes, F_dot_P can become too small, resulting */
- /* in overflows and 'spikes' in a number of glyphs like 'w'. */
- if ( ABS( CUR.F_dot_P ) < 0x4000000L )
- CUR.F_dot_P = 0x40000000L;
- /* Disable cached aspect ratio */
- CUR.metrics.ratio = 0;
- }
- /*******************************************************************
- *
- * Function : Normalize
- *
- * Description : Norms a vector
- *
- * Input : Vx, Vy input vector
- * R unit vector
- *
- * Output : Returns FAILURE if a vector parameter is zero.
- *
- *****************************************************************/
- static Bool Normalize( EXEC_OPS TT_F26Dot6 Vx,
- TT_F26Dot6 Vy,
- TT_UnitVector* R )
- {
- TT_F26Dot6 W;
- Bool S1, S2;
- if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
- {
- Vx *= 0x100;
- Vy *= 0x100;
- W = Norm( Vx, Vy );
- if ( W == 0 )
- {
- /* XXX : Undocumented. It seems that it's possible to try */
- /* to normalize the vector (0,0). Return immediately */
- return SUCCESS;
- }
- R->x = (TT_F2Dot14)MulDiv_Round( Vx, 0x4000L, W );
- R->y = (TT_F2Dot14)MulDiv_Round( Vy, 0x4000L, W );
- return SUCCESS;
- }
- W = Norm( Vx, Vy );
- if ( W <= 0 )
- {
- CUR.error = TT_Err_Divide_By_Zero;
- return FAILURE;
- }
- Vx = MulDiv_Round( Vx, 0x4000L, W );
- Vy = MulDiv_Round( Vy, 0x4000L, W );
- W = Vx * Vx + Vy * Vy;
- /* Now, we want that Sqrt( W ) = 0x4000 */
- /* Or 0x10000000 <= W < 0x10004000 */
- if ( Vx < 0 )
- {
- Vx = -Vx;
- S1 = TRUE;
- }
- else
- S1 = FALSE;
- if ( Vy < 0 )
- {
- Vy = -Vy;
- S2 = TRUE;
- }
- else
- S2 = FALSE;
- while ( W < 0x10000000L )
- {
- /* We need to increase W, by a minimal amount */
- if ( Vx < Vy )
- Vx++;
- else
- Vy++;
- W = Vx * Vx + Vy * Vy;
- }
- while ( W >= 0x10004000L )
- {
- /* We need to decrease W, by a minimal amount */
- if ( Vx < Vy )
- Vx--;
- else
- Vy--;
- W = Vx * Vx + Vy * Vy;
- }
- /* Note that in various cases, we can only */
- /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
- if ( S1 )
- Vx = -Vx;
- if ( S2 )
- Vy = -Vy;
- R->x = (TT_F2Dot14)Vx; /* Type conversion */
- R->y = (TT_F2Dot14)Vy; /* Type conversion */
- return SUCCESS;
- }
- /****************************************************************/
- /* */
- /* MANAGING THE STACK */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* DUP[] : Duplicate top stack element */
- /* CodeRange : $20 */
- static void Ins_DUP( INS_ARG )
- { (void)exc;
- args[1] = args[0];
- }
- /*******************************************/
- /* POP[] : POPs the stack's top elt. */
- /* CodeRange : $21 */
- static void Ins_POP( INS_ARG )
- { (void)exc; (void)args;
- /* nothing to do */
- }
- /*******************************************/
- /* CLEAR[] : Clear the entire stack */
- /* CodeRange : $22 */
- static void Ins_CLEAR( INS_ARG )
- { (void)args;
- CUR.new_top = 0;
- }
- /*******************************************/
- /* SWAP[] : Swap the top two elements */
- /* CodeRange : $23 */
- static void Ins_SWAP( INS_ARG )
- {
- Long L;
- (void)exc;
- L = args[0];
- args[0] = args[1];
- args[1] = L;
- }
- /*******************************************/
- /* DEPTH[] : return the stack depth */
- /* CodeRange : $24 */
- static void Ins_DEPTH( INS_ARG )
- {
- args[0] = CUR.top;
- }
- /*******************************************/
- /* CINDEX[] : copy indexed element */
- /* CodeRange : $25 */
- static void Ins_CINDEX( INS_ARG )
- {
- Long L;
- L = args[0];
- if ( L<0 || L > CUR.args )
- CUR.error = TT_Err_Invalid_Reference;
- else
- args[0] = CUR.stack[CUR.args - L];
- }
- /*******************************************/
- /* MINDEX[] : move indexed element */
- /* CodeRange : $26 */
- static void Ins_MINDEX( INS_ARG )
- {
- Long L, K;
- L = args[0];
- if ( L<0 || L > CUR.args )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- K = CUR.stack[CUR.args - L];
- memmove( (&CUR.stack[CUR.args - L ]),
- (&CUR.stack[CUR.args - L + 1]),
- (L - 1) * sizeof ( Long ) );
- CUR.stack[ CUR.args-1 ] = K;
- }
- /*******************************************/
- /* ROLL[] : roll top three elements */
- /* CodeRange : $8A */
- static void Ins_ROLL( INS_ARG )
- {
- Long A, B, C;
- (void)exc;
- A = args[2];
- B = args[1];
- C = args[0];
- args[2] = C;
- args[1] = A;
- args[0] = B;
- }
- /****************************************************************/
- /* */
- /* MANAGING THE FLOW OF CONTROL */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- static Bool SkipCode( EXEC_OP )
- {
- CUR.IP += CUR.length;
- if ( CUR.IP < CUR.codeSize )
- if ( CALC_Length() == SUCCESS )
- return SUCCESS;
- CUR.error = TT_Err_Code_Overflow;
- return FAILURE;
- }
- /*******************************************/
- /* IF[] : IF test */
- /* CodeRange : $58 */
- static void Ins_IF( INS_ARG )
- {
- Int nIfs;
- Bool Out;
- if ( args[0] != 0 )
- return;
- nIfs = 1;
- Out = 0;
- do
- {
- if ( SKIP_Code() == FAILURE )
- return;
- switch ( CUR.opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
- case 0x1b: /* ELSE */
- Out = (nIfs == 1);
- break;
- case 0x59: /* EIF */
- nIfs--;
- Out = (nIfs == 0);
- break;
- }
- } while ( Out == 0 );
- }
- /*******************************************/
- /* ELSE[] : ELSE */
- /* CodeRange : $1B */
- static void Ins_ELSE( INS_ARG )
- {
- Int nIfs;
- (void)args;
- nIfs = 1;
- do
- {
- if ( SKIP_Code() == FAILURE )
- return;
- switch ( CUR.opcode )
- {
- case 0x58: /* IF */
- nIfs++;
- break;
- case 0x59: /* EIF */
- nIfs--;
- break;
- }
- } while ( nIfs != 0 );
- }
- /*******************************************/
- /* EIF[] : End IF */
- /* CodeRange : $59 */
- static void Ins_EIF( INS_ARG )
- { (void)exc; (void)args;
- /* nothing to do */
- }
- /*******************************************/
- /* JROT[] : Jump Relative On True */
- /* CodeRange : $78 */
- static void Ins_JROT( INS_ARG )
- {
- if ( args[1] != 0 )
- {
- CUR.IP += (Int)(args[0]);
- CUR.step_ins = FALSE;
- }
- }
- /*******************************************/
- /* JMPR[] : JuMP Relative */
- /* CodeRange : $1C */
- static void Ins_JMPR( INS_ARG )
- {
- CUR.IP += (Int)(args[0]);
- CUR.step_ins = FALSE;
- }
- /*******************************************/
- /* JROF[] : Jump Relative On False */
- /* CodeRange : $79 */
- static void Ins_JROF( INS_ARG )
- {
- if ( args[1] == 0 )
- {
- CUR.IP += (Int)(args[0]);
- CUR.step_ins = FALSE;
- }
- }
- /****************************************************************/
- /* */
- /* LOGICAL FUNCTIONS */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* LT[] : Less Than */
- /* CodeRange : $50 */
- static void Ins_LT( INS_ARG )
- { (void)exc;
- if ( args[0] < args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* LTEQ[] : Less Than or EQual */
- /* CodeRange : $51 */
- static void Ins_LTEQ( INS_ARG )
- { (void)exc;
- if ( args[0] <= args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* GT[] : Greater Than */
- /* CodeRange : $52 */
- static void Ins_GT( INS_ARG )
- { (void)exc;
- if ( args[0] > args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* GTEQ[] : Greater Than or EQual */
- /* CodeRange : $53 */
- static void Ins_GTEQ( INS_ARG )
- { (void)exc;
- if ( args[0] >= args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* EQ[] : EQual */
- /* CodeRange : $54 */
- static void Ins_EQ( INS_ARG )
- { (void)exc;
- if ( args[0] == args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* NEQ[] : Not EQual */
- /* CodeRange : $55 */
- static void Ins_NEQ( INS_ARG )
- { (void)exc;
- if ( args[0] != args[1] )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* ODD[] : Odd */
- /* CodeRange : $56 */
- static void Ins_ODD( INS_ARG )
- {
- if ( (CUR_Func_round( args[0], 0L ) & 127) == 64 )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* EVEN[] : Even */
- /* CodeRange : $57 */
- static void Ins_EVEN( INS_ARG )
- {
- if ( (CUR_Func_round( args[0], 0L ) & 127) == 0 )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* AND[] : logical AND */
- /* CodeRange : $5A */
- static void Ins_AND( INS_ARG )
- { (void)exc;
- if ( args[0] != 0 && args[1] != 0 )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* OR[] : logical OR */
- /* CodeRange : $5B */
- static void Ins_OR( INS_ARG )
- { (void)exc;
- if ( args[0] != 0 || args[1] != 0 )
- args[0] = 1;
- else
- args[0] = 0;
- }
- /*******************************************/
- /* NOT[] : logical NOT */
- /* CodeRange : $5C */
- static void Ins_NOT( INS_ARG )
- { (void)exc;
- if ( args[0] != 0 )
- args[0] = 0;
- else
- args[0] = 1;
- }
- /****************************************************************/
- /* */
- /* ARITHMETIC AND MATH INSTRUCTIONS */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* ADD[] : ADD */
- /* CodeRange : $60 */
- static void Ins_ADD( INS_ARG )
- { (void)exc;
- args[0] += args[1];
- }
- /*******************************************/
- /* SUB[] : SUBstract */
- /* CodeRange : $61 */
- static void Ins_SUB( INS_ARG )
- { (void)exc;
- args[0] -= args[1];
- }
- /*******************************************/
- /* DIV[] : DIVide */
- /* CodeRange : $62 */
- static void Ins_DIV( INS_ARG )
- {
- if ( args[1] == 0 )
- {
- CUR.error = TT_Err_Divide_By_Zero;
- return;
- }
- args[0] = MulDiv_Round( args[0], 64L, args[1] );
- DBG_PRINT1(" %d", args[0]);
- }
- /*******************************************/
- /* MUL[] : MULtiply */
- /* CodeRange : $63 */
- static void Ins_MUL( INS_ARG )
- { (void)exc;
- args[0] = MulDiv_Round( args[0], args[1], 64L );
- }
- /*******************************************/
- /* ABS[] : ABSolute value */
- /* CodeRange : $64 */
- static void Ins_ABS( INS_ARG )
- { (void)exc;
- args[0] = ABS( args[0] );
- }
- /*******************************************/
- /* NEG[] : NEGate */
- /* CodeRange : $65 */
- static void Ins_NEG( INS_ARG )
- { (void)exc;
- args[0] = -args[0];
- }
- /*******************************************/
- /* FLOOR[] : FLOOR */
- /* CodeRange : $66 */
- static void Ins_FLOOR( INS_ARG )
- { (void)exc;
- args[0] &= -64;
- }
- /*******************************************/
- /* CEILING[] : CEILING */
- /* CodeRange : $67 */
- static void Ins_CEILING( INS_ARG )
- { (void)exc;
- args[0] = (args[0] + 63) & (-64);
- }
- /*******************************************/
- /* MAX[] : MAXimum */
- /* CodeRange : $68 */
- static void Ins_MAX( INS_ARG )
- { (void)exc;
- if ( args[1] > args[0] )
- args[0] = args[1];
- }
- /*******************************************/
- /* MIN[] : MINimum */
- /* CodeRange : $69 */
- static void Ins_MIN( INS_ARG )
- { (void)exc;
- if ( args[1] < args[0] )
- args[0] = args[1];
- }
- /****************************************************************/
- /* */
- /* COMPENSATING FOR THE ENGINE CHARACTERISTICS */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* ROUND[ab] : ROUND value */
- /* CodeRange : $68-$6B */
- static void Ins_ROUND( INS_ARG )
- {
- args[0] = CUR_Func_round( args[0],
- CUR.metrics.compensations[CUR.opcode - 0x68] );
- }
- /*******************************************/
- /* NROUND[ab]: No ROUNDing of value */
- /* CodeRange : $6C-$6F */
- static void Ins_NROUND( INS_ARG )
- {
- args[0] = Round_None( EXEC_ARGS
- args[0],
- CUR.metrics.compensations[CUR.opcode - 0x6C] );
- }
- /****************************************************************/
- /* */
- /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /* Skip the whole function definition. */
- static void skip_FDEF( EXEC_OP )
- {
- /* We don't allow nested IDEFS & FDEFs. */
- while ( SKIP_Code() == SUCCESS )
- {
- switch ( CUR.opcode )
- {
- case 0x89: /* IDEF */
- case 0x2c: /* FDEF */
- CUR.error = TT_Err_Nested_DEFS;
- return;
- case 0x2d: /* ENDF */
- return;
- }
- }
- }
- /*******************************************/
- /* FDEF[] : Function DEFinition */
- /* CodeRange : $2C */
- static void Ins_FDEF( INS_ARG )
- {
- PDefRecord pRec;
- if ( BOUNDS( args[0], CUR.numFDefs ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- pRec = &CUR.FDefs[args[0]];
- pRec->Range = CUR.curRange;
- pRec->Opc = (Byte)(args[0]);
- pRec->Start = CUR.IP + 1;
- pRec->Active = TRUE;
- skip_FDEF(EXEC_ARG);
- }
- /*******************************************/
- /* ENDF[] : END Function definition */
- /* CodeRange : $2D */
- static void Ins_ENDF( INS_ARG )
- {
- PCallRecord pRec;
- (void)args;
- if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
- {
- CUR.error = TT_Err_ENDF_In_Exec_Stream;
- return;
- }
- CUR.callTop--;
- pRec = &CUR.callStack[CUR.callTop];
- pRec->Cur_Count--;
- CUR.step_ins = FALSE;
- if ( pRec->Cur_Count > 0 )
- {
- CUR.callTop++;
- CUR.IP = pRec->Cur_Restart;
- }
- else
- /* Loop through the current function */
- INS_Goto_CodeRange( pRec->Caller_Range,
- pRec->Caller_IP );
- /* Exit the current call frame. */
- /* NOTE: When the last intruction of a program */
- /* is a CALL or LOOPCALL, the return address */
- /* is always out of the code range. This is */
- /* a valid address, and it's why we do not test */
- /* the result of Ins_Goto_CodeRange() here! */
- }
- /*******************************************/
- /* CALL[] : CALL function */
- /* CodeRange : $2B */
- static void Ins_CALL( INS_ARG )
- {
- PCallRecord pCrec;
- if ( BOUNDS( args[0], CUR.numFDefs ) || !CUR.FDefs[args[0]].Active )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- DBG_PRINT1("%d", args[0]);
- pCrec = &CUR.callStack[CUR.callTop];
- pCrec->Caller_Range = CUR.curRange;
- pCrec->Caller_IP = CUR.IP + 1;
- pCrec->Cur_Count = 1;
- pCrec->Cur_Restart = CUR.FDefs[args[0]].Start;
- CUR.callTop++;
- INS_Goto_CodeRange( CUR.FDefs[args[0]].Range,
- CUR.FDefs[args[0]].Start );
- CUR.step_ins = FALSE;
- }
- /*******************************************/
- /* LOOPCALL[]: LOOP and CALL function */
- /* CodeRange : $2A */
- static void Ins_LOOPCALL( INS_ARG )
- {
- PCallRecord pTCR;
- if ( BOUNDS( args[1], CUR.numFDefs ) || !CUR.FDefs[args[1]].Active )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- if ( args[0] > 0 )
- {
- pTCR = &CUR.callStack[CUR.callTop];
- pTCR->Caller_Range = CUR.curRange;
- pTCR->Caller_IP = CUR.IP + 1;
- pTCR->Cur_Count = (Int)(args[0]);
- pTCR->Cur_Restart = CUR.FDefs[args[1]].Start;
- CUR.callTop++;
- INS_Goto_CodeRange( CUR.FDefs[args[1]].Range,
- CUR.FDefs[args[1]].Start );
- CUR.step_ins = FALSE;
- }
- }
- /*******************************************/
- /* IDEF[] : Instruction DEFinition */
- /* CodeRange : $89 */
- static void Ins_IDEF( INS_ARG )
- {
- if (CUR.countIDefs >= CUR.numIDefs || args[0] > 255)
- CUR.error = TT_Err_Storage_Overflow;
- else
- {
- PDefRecord pTDR;
- CUR.IDefPtr[(Byte)(args[0])] = CUR.countIDefs;
- pTDR = &CUR.IDefs[CUR.countIDefs++];
- pTDR->Opc = (Byte)(args[0]);
- pTDR->Start = CUR.IP + 1;
- pTDR->Range = CUR.curRange;
- pTDR->Active = TRUE;
- skip_FDEF(EXEC_ARG);
- }
- }
- /****************************************************************/
- /* */
- /* PUSHING DATA ONTO THE INTERPRETER STACK */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* NPUSHB[] : PUSH N Bytes */
- /* CodeRange : $40 */
- static void Ins_NPUSHB( INS_ARG )
- {
- Int L, K;
- L = (Int)CUR.code[CUR.IP + 1];
- if ( BOUNDS( L, CUR.stackSize+1-CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- for ( K = 1; K <= L; K++ )
- { args[K - 1] = CUR.code[CUR.IP + K + 1];
- DBG_PRINT1(" %d", args[K - 1]);
- }
- CUR.new_top += L;
- }
- /*******************************************/
- /* NPUSHW[] : PUSH N Words */
- /* CodeRange : $41 */
- static void Ins_NPUSHW( INS_ARG )
- {
- Int L, K;
- L = (Int)CUR.code[CUR.IP + 1];
- if ( BOUNDS( L, CUR.stackSize+1-CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- CUR.IP += 2;
- for ( K = 0; K < L; K++ )
- { args[K] = GET_ShortIns();
- DBG_PRINT1(" %d", args[K]);
- }
- CUR.step_ins = FALSE;
- CUR.new_top += L;
- }
- /*******************************************/
- /* PUSHB[abc]: PUSH Bytes */
- /* CodeRange : $B0-$B7 */
- static void Ins_PUSHB( INS_ARG )
- {
- Int L, K;
- L = ((Int)CUR.opcode - 0xB0 + 1);
- if ( BOUNDS( L, CUR.stackSize+1-CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- for ( K = 1; K <= L; K++ )
- { args[K - 1] = CUR.code[CUR.IP + K];
- DBG_PRINT1(" %d", args[K - 1]);
- }
- }
- /*******************************************/
- /* PUSHW[abc]: PUSH Words */
- /* CodeRange : $B8-$BF */
- static void Ins_PUSHW( INS_ARG )
- {
- Int L, K;
- L = CUR.opcode - 0xB8 + 1;
- if ( BOUNDS( L, CUR.stackSize+1-CUR.top ) )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- CUR.IP++;
- for ( K = 0; K < L; K++ )
- { args[K] = GET_ShortIns();
- DBG_PRINT1(" %d", args[K]);
- }
- CUR.step_ins = FALSE;
- }
- /****************************************************************/
- /* */
- /* MANAGING THE STORAGE AREA */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* RS[] : Read Store */
- /* CodeRange : $43 */
- static void Ins_RS( INS_ARG )
- {
- if ( BOUNDS( args[0], CUR.storeSize ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- args[0] = CUR.storage[args[0]];
- }
- /*******************************************/
- /* WS[] : Write Store */
- /* CodeRange : $42 */
- static void Ins_WS( INS_ARG )
- {
- if ( BOUNDS( args[0], CUR.storeSize ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.storage[args[0]] = args[1];
- }
- /*******************************************/
- /* WCVTP[] : Write CVT in Pixel units */
- /* CodeRange : $44 */
- static void Ins_WCVTP( INS_ARG )
- {
- if ( BOUNDS( args[0], CUR.cvtSize ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR_Func_write_cvt( args[0], args[1] );
- }
- /*******************************************/
- /* WCVTF[] : Write CVT in FUnits */
- /* CodeRange : $70 */
- static void Ins_WCVTF( INS_ARG )
- {
- int ov;
- if ( BOUNDS( args[0], CUR.cvtSize ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- ov = CUR.cvt[args[0]];
- CUR.cvt[args[0]] = FUnits_To_Pixels( EXEC_ARGS args[1] );
- DBG_PRINT3(" cvt[%d]%d:=%d", args[0], ov, CUR.cvt[args[0]]);
- }
- /*******************************************/
- /* RCVT[] : Read CVT */
- /* CodeRange : $45 */
- static void Ins_RCVT( INS_ARG )
- {
- int index;
- if ( BOUNDS( args[0], CUR.cvtSize ) )
- {
- #if 0
- CUR.error = TT_Err_Invalid_Reference;
- return;
- #else
- /* A workaround for the Ghostscript Bug 687604.
- Ported from FreeType 2 : !FT_LOAD_PEDANTIC by default. */
- index=args[0];
- args[0] = 0;
- DBG_PRINT1(" cvt[%d] stubbed with 0", index);
- #endif
- }
- index=args[0];
- args[0] = CUR_Func_read_cvt( index );
- DBG_PRINT3(" cvt[%d]%d:%d", index, CUR.cvt[index], args[0]);
- }
- /****************************************************************/
- /* */
- /* MANAGING THE GRAPHICS STATE */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /*******************************************/
- /* SVTCA[a] : Set F and P vectors to axis */
- /* CodeRange : $00-$01 */
- static void Ins_SVTCA( INS_ARG )
- {
- Short A, B;
- (void)args;
- if ( CUR.opcode & 1 )
- A = 0x4000;
- else
- A = 0;
- B = A ^ 0x4000;
- CUR.GS.freeVector.x = A;
- CUR.GS.projVector.x = A;
- CUR.GS.dualVector.x = A;
- CUR.GS.freeVector.y = B;
- CUR.GS.projVector.y = B;
- CUR.GS.dualVector.y = B;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SPVTCA[a] : Set PVector to Axis */
- /* CodeRange : $02-$03 */
- static void Ins_SPVTCA( INS_ARG )
- {
- Short A, B;
- (void)args;
- if ( CUR.opcode & 1 )
- A = 0x4000;
- else
- A = 0;
- B = A ^ 0x4000;
- CUR.GS.projVector.x = A;
- CUR.GS.dualVector.x = A;
- CUR.GS.projVector.y = B;
- CUR.GS.dualVector.y = B;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SFVTCA[a] : Set FVector to Axis */
- /* CodeRange : $04-$05 */
- static void Ins_SFVTCA( INS_ARG )
- {
- Short A, B;
- (void)args;
- if ( CUR.opcode & 1 )
- A = 0x4000;
- else
- A = 0;
- B = A ^ 0x4000;
- CUR.GS.freeVector.x = A;
- CUR.GS.freeVector.y = B;
- COMPUTE_Funcs();
- }
- static Bool Ins_SxVTL( EXEC_OPS Int aIdx1,
- Int aIdx2,
- Int aOpc,
- TT_UnitVector* Vec )
- {
- Long A, B, C;
- if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
- BOUNDS( aIdx2, CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return FAILURE;
- }
- A = CUR.zp1.cur_x[aIdx2] - CUR.zp2.cur_x[aIdx1];
- B = CUR.zp1.cur_y[aIdx2] - CUR.zp2.cur_y[aIdx1];
- if ( (aOpc & 1) != 0 )
- {
- C = B; /* CounterClockwise rotation */
- B = A;
- A = -C;
- }
- if ( NORMalize( A, B, Vec ) == FAILURE )
- {
- /* When the vector is too small or zero! */
- CUR.error = TT_Err_Ok;
- Vec->x = 0x4000;
- Vec->y = 0;
- }
- return SUCCESS;
- }
- /*******************************************/
- /* SPVTL[a] : Set PVector to Line */
- /* CodeRange : $06-$07 */
- static void Ins_SPVTL( INS_ARG )
- {
- if ( INS_SxVTL( args[1],
- args[0],
- CUR.opcode,
- &CUR.GS.projVector) == FAILURE )
- return;
- CUR.GS.dualVector = CUR.GS.projVector;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SFVTL[a] : Set FVector to Line */
- /* CodeRange : $08-$09 */
- static void Ins_SFVTL( INS_ARG )
- {
- if ( INS_SxVTL( (Int)(args[1]),
- (Int)(args[0]),
- CUR.opcode,
- &CUR.GS.freeVector) == FAILURE )
- return;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SFVTPV[] : Set FVector to PVector */
- /* CodeRange : $0E */
- static void Ins_SFVTPV( INS_ARG )
- { (void)args;
- CUR.GS.freeVector = CUR.GS.projVector;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SDPVTL[a] : Set Dual PVector to Line */
- /* CodeRange : $86-$87 */
- static void Ins_SDPVTL( INS_ARG )
- {
- Long A, B, C;
- Long p1, p2; /* was Int in pas type ERROR */
- p1 = args[1];
- p2 = args[0];
- if ( BOUNDS( p2, CUR.zp1.n_points ) ||
- BOUNDS( p1, CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- A = CUR.zp1.org_x[p2] - CUR.zp2.org_x[p1];
- B = CUR.zp1.org_y[p2] - CUR.zp2.org_y[p1];
- if ( (CUR.opcode & 1) != 0 )
- {
- C = B; /* CounterClockwise rotation */
- B = A;
- A = -C;
- }
- if ( NORMalize( A, B, &CUR.GS.dualVector ) == FAILURE )
- return;
- A = CUR.zp1.cur_x[p2] - CUR.zp2.cur_x[p1];
- B = CUR.zp1.cur_y[p2] - CUR.zp2.cur_y[p1];
- if ( (CUR.opcode & 1) != 0 )
- {
- C = B; /* CounterClockwise rotation */
- B = A;
- A = -C;
- }
- if ( NORMalize( A, B, &CUR.GS.projVector ) == FAILURE )
- return;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SPVFS[] : Set PVector From Stack */
- /* CodeRange : $0A */
- static void Ins_SPVFS( INS_ARG )
- {
- Short S;
- Long X, Y;
- /* Only use low 16bits, then sign extend */
- S = (Short)args[1];
- Y = (Long)S;
- S = (Short)args[0];
- X = (Long)S;
- if ( NORMalize( X, Y, &CUR.GS.projVector ) == FAILURE )
- return;
- CUR.GS.dualVector = CUR.GS.projVector;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* SFVFS[] : Set FVector From Stack */
- /* CodeRange : $0B */
- static void Ins_SFVFS( INS_ARG )
- {
- Short S;
- Long X, Y;
- /* Only use low 16bits, then sign extend */
- S = (Short)args[1];
- Y = (Long)S;
- S = (Short)args[0];
- X = S;
- if ( NORMalize( X, Y, &CUR.GS.freeVector ) == FAILURE )
- return;
- COMPUTE_Funcs();
- }
- /*******************************************/
- /* GPV[] : Get Projection Vector */
- /* CodeRange : $0C */
- static void Ins_GPV( INS_ARG )
- {
- args[0] = CUR.GS.projVector.x;
- args[1] = CUR.GS.projVector.y;
- }
- /*******************************************/
- /* GFV[] : Get Freedom Vector */
- /* CodeRange : $0D */
- static void Ins_GFV( INS_ARG )
- {
- args[0] = CUR.GS.freeVector.x;
- args[1] = CUR.GS.freeVector.y;
- }
- /*******************************************/
- /* SRP0[] : Set Reference Point 0 */
- /* CodeRange : $10 */
- static void Ins_SRP0( INS_ARG )
- {
- CUR.GS.rp0 = (Int)(args[0]);
- }
- /*******************************************/
- /* SRP1[] : Set Reference Point 1 */
- /* CodeRange : $11 */
- static void Ins_SRP1( INS_ARG )
- {
- CUR.GS.rp1 = (Int)(args[0]);
- }
- /*******************************************/
- /* SRP2[] : Set Reference Point 2 */
- /* CodeRange : $12 */
- static void Ins_SRP2( INS_ARG )
- {
- CUR.GS.rp2 = (Int)(args[0]);
- }
- /*******************************************/
- /* SZP0[] : Set Zone Pointer 0 */
- /* CodeRange : $13 */
- static void Ins_SZP0( INS_ARG )
- {
- switch ( args[0] )
- {
- case 0:
- CUR.zp0 = CUR.twilight;
- break;
- case 1:
- CUR.zp0 = CUR.pts;
- break;
- default:
- CUR.error = TT_Err_Invalid_Reference;
- return;
- break;
- }
- CUR.GS.gep0 = (Int)(args[0]);
- }
- /*******************************************/
- /* SZP1[] : Set Zone Pointer 1 */
- /* CodeRange : $14 */
- static void Ins_SZP1( INS_ARG )
- {
- switch ( args[0] )
- {
- case 0:
- CUR.zp1 = CUR.twilight;
- break;
- case 1:
- CUR.zp1 = CUR.pts;
- break;
- default:
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.gep1 = (Int)(args[0]);
- }
- /*******************************************/
- /* SZP2[] : Set Zone Pointer 2 */
- /* CodeRange : $15 */
- static void Ins_SZP2( INS_ARG )
- {
- switch ( args[0] )
- {
- case 0:
- CUR.zp2 = CUR.twilight;
- break;
- case 1:
- CUR.zp2 = CUR.pts;
- break;
- default:
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.gep2 = (Int)(args[0]);
- }
- /*******************************************/
- /* SZPS[] : Set Zone Pointers */
- /* CodeRange : $16 */
- static void Ins_SZPS( INS_ARG )
- {
- switch ( args[0] )
- {
- case 0:
- CUR.zp0 = CUR.twilight;
- break;
- case 1:
- CUR.zp0 = CUR.pts;
- break;
- default:
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.zp1 = CUR.zp0;
- CUR.zp2 = CUR.zp0;
- CUR.GS.gep0 = (Int)(args[0]);
- CUR.GS.gep1 = (Int)(args[0]);
- CUR.GS.gep2 = (Int)(args[0]);
- }
- /*******************************************/
- /* RTHG[] : Round To Half Grid */
- /* CodeRange : $19 */
- static void Ins_RTHG( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_To_Half_Grid;
- CUR.func_round = (TRound_Function)Round_To_Half_Grid;
- }
- /*******************************************/
- /* RTG[] : Round To Grid */
- /* CodeRange : $18 */
- static void Ins_RTG( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_To_Grid;
- CUR.func_round = (TRound_Function)Round_To_Grid;
- }
- /*******************************************/
- /* RTDG[] : Round To Double Grid */
- /* CodeRange : $3D */
- static void Ins_RTDG( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_To_Double_Grid;
- CUR.func_round = (TRound_Function)Round_To_Double_Grid;
- }
- /*******************************************/
- /* RUTG[] : Round Up To Grid */
- /* CodeRange : $7C */
- static void Ins_RUTG( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_Up_To_Grid;
- CUR.func_round = (TRound_Function)Round_Up_To_Grid;
- }
- /*******************************************/
- /* RDTG[] : Round Down To Grid */
- /* CodeRange : $7D */
- static void Ins_RDTG( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_Down_To_Grid;
- CUR.func_round = (TRound_Function)Round_Down_To_Grid;
- }
- /*******************************************/
- /* ROFF[] : Round OFF */
- /* CodeRange : $7A */
- static void Ins_ROFF( INS_ARG )
- { (void)args;
- CUR.GS.round_state = TT_Round_Off;
- CUR.func_round = (TRound_Function)Round_None;
- }
- /*******************************************/
- /* SROUND[] : Super ROUND */
- /* CodeRange : $76 */
- static void Ins_SROUND( INS_ARG )
- {
- SET_SuperRound( 0x4000L, args[0] );
- CUR.GS.round_state = TT_Round_Super;
- CUR.func_round = (TRound_Function)Round_Super;
- }
- /*******************************************/
- /* S45ROUND[]: Super ROUND 45 degrees */
- /* CodeRange : $77 */
- static void Ins_S45ROUND( INS_ARG )
- {
- SET_SuperRound( 0x2D41L, args[0] );
- CUR.GS.round_state = TT_Round_Super_45;
- CUR.func_round = (TRound_Function)Round_Super_45;
- }
- /*******************************************/
- /* SLOOP[] : Set LOOP variable */
- /* CodeRange : $17 */
- static void Ins_SLOOP( INS_ARG )
- {
- CUR.GS.loop = args[0];
- }
- /*******************************************/
- /* SMD[] : Set Minimum Distance */
- /* CodeRange : $1A */
- static void Ins_SMD( INS_ARG )
- {
- CUR.GS.minimum_distance = args[0];
- }
- /*******************************************/
- /* INSTCTRL[]: INSTruction ConTRol */
- /* CodeRange : $8e */
- static void Ins_INSTCTRL( INS_ARG )
- {
- Long K, L;
- K = args[1];
- L = args[0];
- if ( K < 0 || K > 3 )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.GS.instruct_control = (Int)((CUR.GS.instruct_control & (~K)) | (L & K));
- }
- /*******************************************/
- /* SCANCTRL[]: SCAN ConTRol */
- /* CodeRange : $85 */
- static void Ins_SCANCTRL( INS_ARG )
- {
- Int A;
- /* Get Threshold */
- A = (Int)(args[0] & 0xFF);
- if ( A == 0xFF )
- {
- CUR.GS.scan_control = TRUE;
- return;
- }
- else if ( A == 0 )
- {
- CUR.GS.scan_control = FALSE;
- return;
- }
- A *= 64;
- if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
- CUR.GS.scan_control = TRUE;
- if ( (args[0] & 0x200) != 0 && CUR.metrics.rotated )
- CUR.GS.scan_control = TRUE;
- if ( (args[0] & 0x400) != 0 && CUR.metrics.stretched )
- CUR.GS.scan_control = TRUE;
- if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
- CUR.GS.scan_control = FALSE;
- if ( (args[0] & 0x1000) != 0 && CUR.metrics.rotated )
- CUR.GS.scan_control = FALSE;
- if ( (args[0] & 0x2000) != 0 && CUR.metrics.stretched )
- CUR.GS.scan_control = FALSE;
- }
- /*******************************************/
- /* SCANTYPE[]: SCAN TYPE */
- /* CodeRange : $8D */
- static void Ins_SCANTYPE( INS_ARG )
- {
- /* For compatibility with future enhancements, */
- /* we must ignore new modes */
- if ( args[0] >= 0 && args[0] <= 5 )
- {
- if ( args[0] == 3 )
- args[0] = 2;
- CUR.GS.scan_type = (Int)args[0];
- }
- }
- /**********************************************/
- /* SCVTCI[] : Set Control Value Table Cut In */
- /* CodeRange : $1D */
- static void Ins_SCVTCI( INS_ARG )
- {
- CUR.GS.control_value_cutin = (TT_F26Dot6)args[0];
- }
- /**********************************************/
- /* SSWCI[] : Set Single Width Cut In */
- /* CodeRange : $1E */
- static void Ins_SSWCI( INS_ARG )
- {
- CUR.GS.single_width_cutin = (TT_F26Dot6)args[0];
- }
- /**********************************************/
- /* SSW[] : Set Single Width */
- /* CodeRange : $1F */
- static void Ins_SSW( INS_ARG )
- {
- /* XXX : Undocumented or bug in the Windows engine ? */
- /* */
- /* It seems that the value that is read here is */
- /* expressed in 16.16 format, rather than in */
- /* font units.. */
- /* */
- CUR.GS.single_width_value = (TT_F26Dot6)(args[0] >> 10);
- }
- /**********************************************/
- /* FLIPON[] : Set Auto_flip to On */
- /* CodeRange : $4D */
- static void Ins_FLIPON( INS_ARG )
- { (void)args;
- CUR.GS.auto_flip = TRUE;
- }
- /**********************************************/
- /* FLIPOFF[] : Set Auto_flip to Off */
- /* CodeRange : $4E */
- static void Ins_FLIPOFF( INS_ARG )
- { (void)args;
- CUR.GS.auto_flip = FALSE;
- }
- /**********************************************/
- /* SANGW[] : Set Angle Weight */
- /* CodeRange : $7E */
- static void Ins_SANGW( INS_ARG )
- { (void)exc; (void)args;
- /* instruction not supported anymore */
- }
- /**********************************************/
- /* SDB[] : Set Delta Base */
- /* CodeRange : $5E */
- static void Ins_SDB( INS_ARG )
- {
- CUR.GS.delta_base = (Int)args[0];
- }
- /**********************************************/
- /* SDS[] : Set Delta Shift */
- /* CodeRange : $5F */
- static void Ins_SDS( INS_ARG )
- {
- CUR.GS.delta_shift = (Int)args[0];
- }
- /**********************************************/
- /* GC[a] : Get Coordinate projected onto */
- /* CodeRange : $46-$47 */
- /* BULLSHIT: Measures from the original glyph must to be taken */
- /* along the dual projection vector! */
- static void Ins_GC( INS_ARG )
- {
- Long L;
- L = args[0];
- if ( BOUNDS( L, CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- switch ( CUR.opcode & 1 )
- {
- case 0:
- L = CUR_Func_project( CUR.zp2.cur_x[L],
- CUR.zp2.cur_y[L] );
- break;
- case 1:
- L = CUR_Func_dualproj( CUR.zp2.org_x[L],
- CUR.zp2.org_y[L] );
- break;
- }
- args[0] = L;
- }
- /**********************************************/
- /* SCFS[] : Set Coordinate From Stack */
- /* CodeRange : $48 */
- /* */
- /* Formula: */
- /* */
- /* OA := OA + ( value - OA.p )/( f.p ) * f */
- /* */
- static void Ins_SCFS( INS_ARG )
- {
- Long K;
- Int L;
- L = (Int)args[0];
- if ( BOUNDS( args[0], CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- K = CUR_Func_project( CUR.zp2.cur_x[L],
- CUR.zp2.cur_y[L] );
- CUR_Func_move( &CUR.zp2, L, args[1] - K );
- /* not part of the specs, but here for safety */
- if ( CUR.GS.gep2 == 0 )
- {
- CUR.zp2.org_x[L] = CUR.zp2.cur_x[L];
- CUR.zp2.org_y[L] = CUR.zp2.cur_y[L];
- }
- }
- /**********************************************/
- /* MD[a] : Measure Distance */
- /* CodeRange : $49-$4A */
- /* BULLSHIT: Measure taken in the original glyph must be along */
- /* the dual projection vector. */
- /* Second BULLSHIT: Flag attributes are inverted! */
- /* 0 => measure distance in original outline */
- /* 1 => measure distance in grid-fitted outline */
- static void Ins_MD( INS_ARG )
- {
- Long K, L;
- TT_F26Dot6 D;
- K = args[1];
- L = args[0];
- if( BOUNDS( args[0], CUR.zp2.n_points ) ||
- BOUNDS( args[1], CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( CUR.opcode & 1 )
- D = CUR_Func_project( CUR.zp2.cur_x[L] - CUR.zp1.cur_x[K],
- CUR.zp2.cur_y[L] - CUR.zp1.cur_y[K] );
- else
- D = CUR_Func_dualproj( CUR.zp2.org_x[L] - CUR.zp1.org_x[K],
- CUR.zp2.org_y[L] - CUR.zp1.org_y[K] );
- args[0] = D;
- }
- /**********************************************/
- /* MPPEM[] : Measure Pixel Per EM */
- /* CodeRange : $4B */
- static void Ins_MPPEM( INS_ARG )
- {
- args[0] = CURRENT_Ppem();
- DBG_PRINT1(" %d", args[0]);
- }
- /**********************************************/
- /* MPS[] : Measure PointSize */
- /* CodeRange : $4C */
- static void Ins_MPS( INS_ARG )
- {
- args[0] = CUR.metrics.pointSize;
- }
- /****************************************************************/
- /* */
- /* MANAGING OUTLINES */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- /**********************************************/
- /* FLIPPT[] : FLIP PoinT */
- /* CodeRange : $80 */
- static void Ins_FLIPPT( INS_ARG )
- {
- Long point;
- (void)args;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.pts.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- CUR.pts.touch[point] ^= TT_Flag_On_Curve;
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* FLIPRGON[]: FLIP RanGe ON */
- /* CodeRange : $81 */
- static void Ins_FLIPRGON( INS_ARG )
- {
- Long I, K, L;
- K = args[1];
- L = args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- for ( I = L; I <= K; I++ )
- CUR.pts.touch[I] |= TT_Flag_On_Curve;
- }
- /**********************************************/
- /* FLIPRGOFF : FLIP RanGe OFF */
- /* CodeRange : $82 */
- static void Ins_FLIPRGOFF( INS_ARG )
- {
- Long I, K, L;
- K = args[1];
- L = args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- for ( I = L; I <= K; I++ )
- CUR.pts.touch[I] &= ~TT_Flag_On_Curve;
- }
- static Bool Compute_Point_Displacement( EXEC_OPS
- PCoordinates x,
- PCoordinates y,
- PGlyph_Zone zone,
- Int* refp )
- {
- TGlyph_Zone zp;
- Int p;
- TT_F26Dot6 d;
- if ( CUR.opcode & 1 )
- {
- zp = CUR.zp0;
- p = CUR.GS.rp1;
- }
- else
- {
- zp = CUR.zp1;
- p = CUR.GS.rp2;
- }
- if ( BOUNDS( p, zp.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Displacement;
- return FAILURE;
- }
- *zone = zp;
- *refp = p;
- d = CUR_Func_project( zp.cur_x[p] - zp.org_x[p],
- zp.cur_y[p] - zp.org_y[p] );
- *x = MulDiv_Round(d, (Long)CUR.GS.freeVector.x * 0x10000L, CUR.F_dot_P );
- *y = MulDiv_Round(d, (Long)CUR.GS.freeVector.y * 0x10000L, CUR.F_dot_P );
- return SUCCESS;
- }
- static void Move_Zp2_Point( EXEC_OPS
- Long point,
- TT_F26Dot6 dx,
- TT_F26Dot6 dy,
- Bool touch )
- {
- if ( CUR.GS.freeVector.x != 0 )
- {
- CUR.zp2.cur_x[point] += dx;
- if ( touch )
- CUR.zp2.touch[point] |= TT_Flag_Touched_X;
- }
- if ( CUR.GS.freeVector.y != 0 )
- {
- CUR.zp2.cur_y[point] += dy;
- if ( touch )
- CUR.zp2.touch[point] |= TT_Flag_Touched_Y;
- }
- }
- /**********************************************/
- /* SHP[a] : SHift Point by the last point */
- /* CodeRange : $32-33 */
- static void Ins_SHP( INS_ARG )
- {
- TGlyph_Zone zp;
- Int refp;
- TT_F26Dot6 dx,
- dy;
- Long point;
- (void)args;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* undocumented: SHP touches the points */
- MOVE_Zp2_Point( point, dx, dy, TRUE );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* SHC[a] : SHift Contour */
- /* CodeRange : $34-35 */
- static void Ins_SHC( INS_ARG )
- {
- TGlyph_Zone zp;
- Int refp;
- TT_F26Dot6 dx,
- dy;
- Long contour, i;
- Int first_point, last_point;
- contour = args[0];
- if ( BOUNDS( args[0], CUR.pts.n_contours ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- if ( contour == 0 )
- first_point = 0;
- else
- first_point = CUR.pts.contours[contour-1] + 1;
- last_point = CUR.pts.contours[contour];
- /* undocumented: SHC doesn't touch the points */
- for ( i = first_point; i <= last_point; i++ )
- {
- if ( zp.cur_x != CUR.zp2.cur_x || refp != i )
- MOVE_Zp2_Point( i, dx, dy, FALSE );
- }
- }
- /**********************************************/
- /* SHZ[a] : SHift Zone */
- /* CodeRange : $36-37 */
- static void Ins_SHZ( INS_ARG )
- {
- TGlyph_Zone zp;
- Int refp;
- TT_F26Dot6 dx,
- dy;
- Int last_point;
- Long i;
- if ( BOUNDS( args[0], 2 ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
- return;
- last_point = zp.n_points - 1;
- /* undocumented: SHZ doesn't touch the points */
- for ( i = 0; i <= last_point; i++ )
- {
- if ( zp.cur_x != CUR.zp2.cur_x || refp != i )
- MOVE_Zp2_Point( i, dx, dy, FALSE );
- }
- }
- /**********************************************/
- /* SHPIX[] : SHift points by a PIXel amount */
- /* CodeRange : $38 */
- static void Ins_SHPIX( INS_ARG )
- {
- TT_F26Dot6 dx, dy;
- Long point;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- dx = MulDiv_Round( args[0],
- (Long)CUR.GS.freeVector.x,
- 0x4000 );
- dy = MulDiv_Round( args[0],
- (Long)CUR.GS.freeVector.y,
- 0x4000 );
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- MOVE_Zp2_Point( point, dx, dy, TRUE );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* MSIRP[a] : Move Stack Indirect Relative */
- /* CodeRange : $3A-$3B */
- static void Ins_MSIRP( INS_ARG )
- {
- Int point;
- TT_F26Dot6 distance;
- point = (Int)args[0];
- if ( BOUNDS( args[0], CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: Undocumented behaviour */
- if ( CUR.GS.gep0 == 0 ) /* if in twilight zone */
- {
- CUR.zp1.org_x[point] = CUR.zp0.org_x[CUR.GS.rp0];
- CUR.zp1.org_y[point] = CUR.zp0.org_y[CUR.GS.rp0];
- CUR.zp1.cur_x[point] = CUR.zp1.org_x[point];
- CUR.zp1.cur_y[point] = CUR.zp1.org_y[point];
- }
- distance = CUR_Func_project( CUR.zp1.cur_x[point] -
- CUR.zp0.cur_x[CUR.GS.rp0],
- CUR.zp1.cur_y[point] -
- CUR.zp0.cur_y[CUR.GS.rp0] );
- CUR_Func_move( &CUR.zp1, point, args[1] - distance );
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
- if ( (CUR.opcode & 1) != 0 )
- CUR.GS.rp0 = point;
- }
- /**********************************************/
- /* MDAP[a] : Move Direct Absolute Point */
- /* CodeRange : $2E-$2F */
- static void Ins_MDAP( INS_ARG )
- {
- Int point;
- TT_F26Dot6 cur_dist,
- distance;
- point = (Int)args[0];
- if ( BOUNDS( args[0], CUR.zp0.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? ? */
- if ( (CUR.opcode & 1) != 0 )
- {
- cur_dist = CUR_Func_project( CUR.zp0.cur_x[point],
- CUR.zp0.cur_y[point] );
- distance = CUR_Func_round( cur_dist,
- CUR.metrics.compensations[0] ) - cur_dist;
- }
- else
- distance = 0;
- CUR_Func_move( &CUR.zp0, point, distance );
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
- }
- /**********************************************/
- /* MIAP[a] : Move Indirect Absolute Point */
- /* CodeRange : $3E-$3F */
- static void Ins_MIAP( INS_ARG )
- {
- Int cvtEntry, point;
- TT_F26Dot6 distance,
- org_dist;
- cvtEntry = (Int)args[1];
- point = (Int)args[0];
- if ( BOUNDS( args[0], CUR.zp0.n_points ) ||
- BOUNDS( args[1], CUR.cvtSize ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* Undocumented: */
- /* */
- /* The behaviour of an MIAP instruction is quite */
- /* different when used in the twilight zone. */
- /* */
- /* First, no control value cutin test is performed */
- /* as it would fail anyway. Second, the original */
- /* point, i.e. (org_x,org_y) of zp0.point, is set */
- /* to the absolute, unrounded distance found in */
- /* the CVT. */
- /* */
- /* This is used in the CVT programs of the Microsoft */
- /* fonts Arial, Times, etc., in order to re-adjust */
- /* some key font heights. It allows the use of the */
- /* IP instruction in the twilight zone, which */
- /* otherwise would be "illegal" according to the */
- /* specs :) */
- /* */
- /* We implement it with a special sequence for the */
- /* twilight zone. This is a bad hack, but it seems */
- /* to work. */
- distance = CUR_Func_read_cvt( cvtEntry );
- DBG_PRINT3(" cvtEntry=%d point=%d distance=%d", cvtEntry, point, distance);
- if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
- {
- CUR.zp0.org_x[point] = MulDiv_Round( CUR.GS.freeVector.x,
- distance, 0x4000L );
- CUR.zp0.cur_x[point] = CUR.zp0.org_x[point];
- CUR.zp0.org_y[point] = MulDiv_Round( CUR.GS.freeVector.y,
- distance, 0x4000L );
- CUR.zp0.cur_y[point] = CUR.zp0.org_y[point];
- }
- org_dist = CUR_Func_project( CUR.zp0.cur_x[point],
- CUR.zp0.cur_y[point] );
- if ( (CUR.opcode & 1) != 0 ) /* rounding and control cutin flag */
- {
- if ( ABS(distance - org_dist) > CUR.GS.control_value_cutin )
- distance = org_dist;
- distance = CUR_Func_round( distance, CUR.metrics.compensations[0] );
- }
- CUR_Func_move( &CUR.zp0, point, distance - org_dist );
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
- }
- /**********************************************/
- /* MDRP[abcde] : Move Direct Relative Point */
- /* CodeRange : $C0-$DF */
- static void Ins_MDRP( INS_ARG )
- {
- Int point;
- TT_F26Dot6 distance,
- org_dist;
- point = (Int)args[0];
- if ( BOUNDS( args[0], CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- /* XXX: Is there some undocumented feature while in the */
- /* twilight zone? */
- org_dist = CUR_Func_dualproj( CUR.zp1.org_x[point] -
- CUR.zp0.org_x[CUR.GS.rp0],
- CUR.zp1.org_y[point] -
- CUR.zp0.org_y[CUR.GS.rp0] );
- /* single width cutin test */
- if ( ABS(org_dist) < CUR.GS.single_width_cutin )
- {
- if ( org_dist >= 0 )
- org_dist = CUR.GS.single_width_value;
- else
- org_dist = -CUR.GS.single_width_value;
- }
- /* round flag */
- if ( (CUR.opcode & 4) != 0 )
- distance = CUR_Func_round( org_dist,
- CUR.metrics.compensations[CUR.opcode & 3] );
- else
- distance = Round_None( EXEC_ARGS
- org_dist,
- CUR.metrics.compensations[CUR.opcode & 3] );
- /* minimum distance flag */
- if ( (CUR.opcode & 8) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
- }
- else
- {
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
- }
- }
- /* now move the point */
- org_dist = CUR_Func_project( CUR.zp1.cur_x[point] -
- CUR.zp0.cur_x[CUR.GS.rp0],
- CUR.zp1.cur_y[point] -
- CUR.zp0.cur_y[CUR.GS.rp0] );
- CUR_Func_move( &CUR.zp1, point, distance - org_dist );
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
- if ( (CUR.opcode & 16) != 0 )
- CUR.GS.rp0 = point;
- }
- /**********************************************/
- /* MIRP[abcde] : Move Indirect Relative Point */
- /* CodeRange : $E0-$FF */
- static void Ins_MIRP( INS_ARG )
- {
- Int point,
- cvtEntry;
- TT_F26Dot6 cvt_dist,
- distance,
- cur_dist,
- org_dist;
- point = (Int)args[0];
- cvtEntry = (Int)args[1];
- /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
- if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
- BOUNDS( args[1]+1, CUR.cvtSize+1 ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- if ( args[1] < 0 )
- cvt_dist = 0;
- else
- cvt_dist = CUR_Func_read_cvt( cvtEntry );
- /* single width test */
- if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin )
- {
- if ( cvt_dist >= 0 )
- cvt_dist = CUR.GS.single_width_value;
- else
- cvt_dist = -CUR.GS.single_width_value;
- }
- /* XXX : Undocumented - twilight zone */
- if ( CUR.GS.gep1 == 0 )
- {
- CUR.zp1.org_x[point] = CUR.zp0.org_x[CUR.GS.rp0] +
- MulDiv_Round( cvt_dist,
- CUR.GS.freeVector.x,
- 0x4000 );
- CUR.zp1.org_y[point] = CUR.zp0.org_y[CUR.GS.rp0] +
- MulDiv_Round( cvt_dist,
- CUR.GS.freeVector.y,
- 0x4000 );
- CUR.zp1.cur_x[point] = CUR.zp1.org_x[point];
- CUR.zp1.cur_y[point] = CUR.zp1.org_y[point];
- }
- org_dist = CUR_Func_dualproj( CUR.zp1.org_x[point] -
- CUR.zp0.org_x[CUR.GS.rp0],
- CUR.zp1.org_y[point] -
- CUR.zp0.org_y[CUR.GS.rp0] );
- cur_dist = CUR_Func_project( CUR.zp1.cur_x[point] -
- CUR.zp0.cur_x[CUR.GS.rp0],
- CUR.zp1.cur_y[point] -
- CUR.zp0.cur_y[CUR.GS.rp0] );
- /* auto-flip test */
- if ( CUR.GS.auto_flip )
- {
- if ( (org_dist ^ cvt_dist) < 0 )
- cvt_dist = -cvt_dist;
- }
- /* control value cutin and round */
- if ( (CUR.opcode & 4) != 0 )
- {
- /* XXX: Undocumented : only perform cut-in test when both points */
- /* refer to the same zone. */
- if ( CUR.GS.gep0 == CUR.GS.gep1 )
- if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
- cvt_dist = org_dist;
- distance = CUR_Func_round( cvt_dist,
- CUR.metrics.compensations[CUR.opcode & 3] );
- }
- else
- distance = Round_None( EXEC_ARGS
- cvt_dist,
- CUR.metrics.compensations[CUR.opcode & 3] );
- /* minimum distance test */
- if ( (CUR.opcode & 8) != 0 )
- {
- if ( org_dist >= 0 )
- {
- if ( distance < CUR.GS.minimum_distance )
- distance = CUR.GS.minimum_distance;
- }
- else
- {
- if ( distance > -CUR.GS.minimum_distance )
- distance = -CUR.GS.minimum_distance;
- }
- }
- CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
- CUR.GS.rp1 = CUR.GS.rp0;
- if ( (CUR.opcode & 16) != 0 )
- CUR.GS.rp0 = point;
- /* UNDOCUMENTED! */
- CUR.GS.rp2 = point;
- }
- /**********************************************/
- /* ALIGNRP[] : ALIGN Relative Point */
- /* CodeRange : $3C */
- static void Ins_ALIGNRP( INS_ARG )
- {
- Int point;
- TT_F26Dot6 distance;
- (void)args;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (Int)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- distance = CUR_Func_project( CUR.zp1.cur_x[point] -
- CUR.zp0.cur_x[CUR.GS.rp0],
- CUR.zp1.cur_y[point] -
- CUR.zp0.cur_y[CUR.GS.rp0] );
- CUR_Func_move( &CUR.zp1, point, -distance );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* AA[] : Adjust Angle */
- /* CodeRange : $7F */
- static void Ins_AA( INS_ARG )
- { (void)exc; (void)args;
- /* Intentional - no longer supported */
- }
- /**********************************************/
- /* ISECT[] : moves point to InterSECTion */
- /* CodeRange : $0F */
- static void Ins_ISECT( INS_ARG )
- {
- Long point, /* are these Ints or Longs? */
- a0, a1,
- b0, b1;
- TT_F26Dot6 discriminant;
- TT_F26Dot6 dx, dy,
- dax, day,
- dbx, dby;
- TT_F26Dot6 val;
- TT_Vector R;
- point = args[0];
- a0 = args[1];
- a1 = args[2];
- b0 = args[3];
- b1 = args[4];
- if ( BOUNDS( b0, CUR.zp0.n_points ) ||
- BOUNDS( b1, CUR.zp0.n_points ) ||
- BOUNDS( a0, CUR.zp1.n_points ) ||
- BOUNDS( a1, CUR.zp1.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- dbx = CUR.zp0.cur_x[b1] - CUR.zp0.cur_x[b0];
- dby = CUR.zp0.cur_y[b1] - CUR.zp0.cur_y[b0];
- dax = CUR.zp1.cur_x[a1] - CUR.zp1.cur_x[a0];
- day = CUR.zp1.cur_y[a1] - CUR.zp1.cur_y[a0];
- dx = CUR.zp0.cur_x[b0] - CUR.zp1.cur_x[a0];
- dy = CUR.zp0.cur_y[b0] - CUR.zp1.cur_y[a0];
- CUR.zp2.touch[point] |= TT_Flag_Touched_Both;
- discriminant = MulDiv_Round( dax, -dby, 0x40L ) +
- MulDiv_Round( day, dbx, 0x40L );
- if ( ABS( discriminant ) >= 0x40 )
- {
- val = MulDiv_Round( dx, -dby, 0x40L ) + MulDiv_Round( dy, dbx, 0x40L );
- R.x = MulDiv_Round( val, dax, discriminant );
- R.y = MulDiv_Round( val, day, discriminant );
- CUR.zp2.cur_x[point] = CUR.zp1.cur_x[a0] + R.x;
- CUR.zp2.cur_y[point] = CUR.zp1.cur_y[a0] + R.y;
- }
- else
- {
- /* else, take the middle of the middles of A and B */
- CUR.zp2.cur_x[point] = ( CUR.zp1.cur_x[a0] +
- CUR.zp1.cur_x[a1] +
- CUR.zp0.cur_x[b0] +
- CUR.zp1.cur_x[b1] ) / 4;
- CUR.zp2.cur_y[point] = ( CUR.zp1.cur_y[a0] +
- CUR.zp1.cur_y[a1] +
- CUR.zp0.cur_y[b0] +
- CUR.zp1.cur_y[b1] ) / 4;
- }
- }
- /**********************************************/
- /* ALIGNPTS[] : ALIGN PoinTS */
- /* CodeRange : $27 */
- static void Ins_ALIGNPTS( INS_ARG )
- {
- Int p1, p2;
- TT_F26Dot6 distance;
- p1 = (Int)args[0];
- p2 = (Int)args[1];
- if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
- BOUNDS( args[1], CUR.zp0.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- distance = CUR_Func_project( CUR.zp0.cur_x[p2] -
- CUR.zp1.cur_x[p1],
- CUR.zp0.cur_y[p2] -
- CUR.zp1.cur_x[p1] ) / 2;
- CUR_Func_move( &CUR.zp1, p1, distance );
- CUR_Func_move( &CUR.zp0, p2, -distance );
- }
- /**********************************************/
- /* IP[] : Interpolate Point */
- /* CodeRange : $39 */
- static void Ins_IP( INS_ARG )
- {
- TT_F26Dot6 org_a, org_b, org_x,
- cur_a, cur_b, cur_x,
- distance;
- Int point;
- (void)args;
- if ( CUR.top < CUR.GS.loop )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- org_a = CUR_Func_dualproj( CUR.zp0.org_x[CUR.GS.rp1],
- CUR.zp0.org_y[CUR.GS.rp1] );
- org_b = CUR_Func_dualproj( CUR.zp1.org_x[CUR.GS.rp2],
- CUR.zp1.org_y[CUR.GS.rp2] );
- cur_a = CUR_Func_project( CUR.zp0.cur_x[CUR.GS.rp1],
- CUR.zp0.cur_y[CUR.GS.rp1] );
- cur_b = CUR_Func_project( CUR.zp1.cur_x[CUR.GS.rp2],
- CUR.zp1.cur_y[CUR.GS.rp2] );
- while ( CUR.GS.loop > 0 )
- {
- CUR.args--;
- point = (Int)CUR.stack[CUR.args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- org_x = CUR_Func_dualproj( CUR.zp2.org_x[point],
- CUR.zp2.org_y[point] );
- cur_x = CUR_Func_project( CUR.zp2.cur_x[point],
- CUR.zp2.cur_y[point] );
- if ( ( org_a <= org_b && org_x <= org_a ) ||
- ( org_a > org_b && org_x >= org_a ) )
- distance = ( cur_a - org_a ) + ( org_x - cur_x );
- else if ( ( org_a <= org_b && org_x >= org_b ) ||
- ( org_a > org_b && org_x < org_b ) )
- distance = ( cur_b - org_b ) + ( org_x - cur_x );
- else
- /* note: it seems that rounding this value isn't a good */
- /* idea (cf. width of capital 'S' in Times) */
- distance = MulDiv_Round( cur_b - cur_a,
- org_x - org_a,
- org_b - org_a ) + ( cur_a - cur_x );
- CUR_Func_move( &CUR.zp2, point, distance );
- CUR.GS.loop--;
- }
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* UTP[a] : UnTouch Point */
- /* CodeRange : $29 */
- static void Ins_UTP( INS_ARG )
- {
- Byte mask;
- if ( BOUNDS( args[0], CUR.zp0.n_points ) )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- mask = 0xFF;
- if ( CUR.GS.freeVector.x != 0 )
- mask &= ~TT_Flag_Touched_X;
- if ( CUR.GS.freeVector.y != 0 )
- mask &= ~TT_Flag_Touched_Y;
- CUR.zp0.touch[args[0]] &= mask;
- }
- /* Local variables for Ins_IUP: */
- struct LOC_Ins_IUP
- {
- PCoordinates orgs; /* original and current coordinate */
- PCoordinates curs; /* arrays */
- };
- static void Shift( Int p1,
- Int p2,
- Int p,
- struct LOC_Ins_IUP* LINK )
- {
- Int i;
- TT_F26Dot6 x;
- x = LINK->curs[p] - LINK->orgs[p];
- for ( i = p1; i < p; i++ )
- LINK->curs[i] += x;
- for ( i = p + 1; i <= p2; i++ )
- LINK->curs[i] += x;
- }
- static void Interp( Int p1, Int p2,
- Int ref1, Int ref2,
- struct LOC_Ins_IUP* LINK )
- {
- Long i;
- TT_F26Dot6 x, x1, x2, d1, d2;
- if ( p1 > p2 )
- return;
- x1 = LINK->orgs[ref1];
- d1 = LINK->curs[ref1] - LINK->orgs[ref1];
- x2 = LINK->orgs[ref2];
- d2 = LINK->curs[ref2] - LINK->orgs[ref2];
- if ( x1 == x2 )
- {
- for ( i = p1; i <= p2; i++ )
- {
- x = LINK->orgs[i];
- if ( x <= x1 )
- x += d1;
- else
- x += d2;
- LINK->curs[i] = x;
- }
- return;
- }
- if ( x1 < x2 )
- {
- for ( i = p1; i <= p2; i++ )
- {
- x = LINK->orgs[i];
- if ( x <= x1 )
- x += d1;
- else
- {
- if ( x >= x2 )
- x += d2;
- else
- x = LINK->curs[ref1] +
- MulDiv_Round( x - x1,
- LINK->curs[ref2] - LINK->curs[ref1],
- x2 - x1 );
- }
- LINK->curs[i] = x;
- }
- return;
- }
- /* x2 < x1 */
- for ( i = p1; i <= p2; i++ )
- {
- x = LINK->orgs[i];
- if ( x <= x2 )
- x += d2;
- else
- {
- if ( x >= x1 )
- x += d1;
- else
- x = LINK->curs[ref1] +
- MulDiv_Round( x - x1,
- LINK->curs[ref2] - LINK->curs[ref1],
- x2 - x1 );
- }
- LINK->curs[i] = x;
- }
- }
- /**********************************************/
- /* IUP[a] : Interpolate Untouched Points */
- /* CodeRange : $30-$31 */
- static void Ins_IUP( INS_ARG )
- {
- struct LOC_Ins_IUP V;
- unsigned char mask;
- Long first_point; /* first point of contour */
- Long end_point; /* end point (last+1) of contour */
- Long first_touched; /* first touched point in contour */
- Long cur_touched; /* current touched point in contour */
- Long point; /* current point */
- Long contour; /* current contour */
- (void)args;
- if ( CUR.opcode & 1 )
- {
- mask = TT_Flag_Touched_X;
- V.orgs = CUR.pts.org_x;
- V.curs = CUR.pts.cur_x;
- }
- else
- {
- mask = TT_Flag_Touched_Y;
- V.orgs = CUR.pts.org_y;
- V.curs = CUR.pts.cur_y;
- }
- contour = 0;
- point = 0;
- do
- {
- end_point = CUR.pts.contours[contour];
- first_point = point;
- while ( point <= end_point && (CUR.pts.touch[point] & mask) == 0 )
- point++;
- if ( point <= end_point )
- {
- first_touched = point;
- cur_touched = point;
- point++;
- while ( point <= end_point )
- {
- if ( (CUR.pts.touch[point] & mask) != 0 )
- {
- Interp( (Int)(cur_touched + 1),
- (Int)(point - 1),
- (Int)cur_touched,
- (Int)point,
- &V );
- cur_touched = point;
- }
- point++;
- }
- if ( cur_touched == first_touched )
- Shift( (Int)first_point, (Int)end_point, (Int)cur_touched, &V );
- else
- {
- Interp((Int)(cur_touched + 1),
- (Int)(end_point),
- (Int)(cur_touched),
- (Int)(first_touched),
- &V );
- Interp((Int)(first_point),
- (Int)(first_touched - 1),
- (Int)(cur_touched),
- (Int)(first_touched),
- &V );
- }
- }
- contour++;
- } while ( contour < CUR.pts.n_contours );
- }
- /**********************************************/
- /* DELTAPn[] : DELTA Exceptions P1, P2, P3 */
- /* CodeRange : $5D,$71,$72 */
- static void Ins_DELTAP( INS_ARG )
- {
- Int k;
- Long A, B, C, nump;
- nump = args[0];
- for ( k = 1; k <= nump; k++ )
- {
- if ( CUR.args < 2 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= 2;
- A = CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
- #if 0
- if ( BOUNDS( A, CUR.zp0.n_points ) )
- #else
- /* igorm changed : allow phantom points (Altona.Page_3.2002-09-27.pdf). */
- if ( BOUNDS( A, CUR.zp0.n_points + 2 ) )
- #endif
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- C = (B & 0xF0) >> 4;
- switch ( CUR.opcode )
- {
- case 0x5d:
- break;
- case 0x71:
- C += 16;
- break;
- case 0x72:
- C += 32;
- break;
- }
- C += CUR.GS.delta_base;
- if ( CURRENT_Ppem() == C )
- {
- B = (B & 0xF) - 8;
- if ( B >= 0 )
- B++;
- B = B * 64 / (1L << CUR.GS.delta_shift);
- CUR_Func_move( &CUR.zp0, (Int)A, (Int)B );
- }
- }
- CUR.new_top = CUR.args;
- }
- /**********************************************/
- /* DELTACn[] : DELTA Exceptions C1, C2, C3 */
- /* CodeRange : $73,$74,$75 */
- static void Ins_DELTAC( INS_ARG )
- {
- Long nump, k;
- Long A, B, C;
- nump = args[0];
- for ( k = 1; k <= nump; k++ )
- {
- if ( CUR.args < 2 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
- }
- CUR.args -= 2;
- A = CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
- if ( A >= CUR.cvtSize )
- {
- CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- C = ((unsigned long)(B & 0xF0)) >> 4;
- switch ( CUR.opcode )
- {
- case 0x73:
- break;
- case 0x74:
- C += 16;
- break;
- case 0x75:
- C += 32;
- break;
- }
- C += CUR.GS.delta_base;
- if ( CURRENT_Ppem() == C )
- {
- B = (B & 0xF) - 8;
- if ( B >= 0 )
- B++;
- B = B * 64 / (1L << CUR.GS.delta_shift);
- CUR_Func_move_cvt( A, B );
- }
- }
- CUR.new_top = CUR.args;
- }
- /****************************************************************/
- /* */
- /* MISC. INSTRUCTIONS */
- /* */
- /****************************************************************/
- /***********************************************************/
- /* DEBUG[] : DEBUG. Unsupported */
- /* CodeRange : $4F */
- /* NOTE : The original instruction pops a value from the stack */
- static void Ins_DEBUG( INS_ARG )
- { (void)args;
- CUR.error = TT_Err_Debug_OpCode;
- }
- /**********************************************/
- /* GETINFO[] : GET INFOrmation */
- /* CodeRange : $88 */
- static void Ins_GETINFO( INS_ARG )
- {
- Long K;
- K = 0;
- /* We return then Windows 3.1 version number */
- /* for the font scaler */
- if ( (args[0] & 1) != 0 )
- K = 3;
- /* Has the glyph been rotated ? */
- if ( CUR.metrics.rotated )
- K |= 0x80;
- /* Has the glyph been stretched ? */
- if ( CUR.metrics.stretched )
- K |= 0x100;
- args[0] = K;
- }
- static void Ins_UNKNOWN( INS_ARG )
- { /* Rewritten by igorm. */
- Byte i;
- TDefRecord* def;
- PCallRecord call;
- # if 0 /* The condition below appears always false
- due to limited range of data type
- - skip it to quiet a compiler warning. */
- if (CUR.opcode > sizeof(CUR.IDefPtr) / sizeof(CUR.IDefPtr[0])) {
- CUR.error = TT_Err_Invalid_Opcode;
- return;
- }
- # endif
- i = CUR.IDefPtr[(Byte)CUR.opcode];
- if (i >= CUR.numIDefs)
- {
- CUR.error = TT_Err_Invalid_Opcode;
- return;
- }
- def = &CUR.IDefs[i];
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- return;
- }
- call = CUR.callStack + CUR.callTop++;
- call->Caller_Range = CUR.curRange;
- call->Caller_IP = CUR.IP+1;
- call->Cur_Count = 1;
- call->Cur_Restart = def->Start;
- INS_Goto_CodeRange( def->Range, def->Start );
- CUR.step_ins = FALSE;
- return;
- }
- static struct { const char *sName; TInstruction_Function p; } Instruct_Dispatch[256] =
- {
- /* Opcodes are gathered in groups of 16. */
- /* Please keep the spaces as they are. */
- {" SVTCA y ", Ins_SVTCA }
- ,{" SVTCA x ", Ins_SVTCA }
- ,{" SPvTCA y ", Ins_SPVTCA }
- ,{" SPvTCA x ", Ins_SPVTCA }
- ,{" SFvTCA y ", Ins_SFVTCA }
- ,{" SFvTCA x ", Ins_SFVTCA }
- ,{" SPvTL // ", Ins_SPVTL }
- ,{" SPvTL + ", Ins_SPVTL }
- ,{" SFvTL // ", Ins_SFVTL }
- ,{" SFvTL + ", Ins_SFVTL }
- ,{" SPvFS ", Ins_SPVFS }
- ,{" SFvFS ", Ins_SFVFS }
- ,{" GPV ", Ins_GPV }
- ,{" GFV ", Ins_GFV }
- ,{" SFvTPv ", Ins_SFVTPV }
- ,{" ISECT ", Ins_ISECT }
- ,{" SRP0 ", Ins_SRP0 }
- ,{" SRP1 ", Ins_SRP1 }
- ,{" SRP2 ", Ins_SRP2 }
- ,{" SZP0 ", Ins_SZP0 }
- ,{" SZP1 ", Ins_SZP1 }
- ,{" SZP2 ", Ins_SZP2 }
- ,{" SZPS ", Ins_SZPS }
- ,{" SLOOP ", Ins_SLOOP }
- ,{" RTG ", Ins_RTG }
- ,{" RTHG ", Ins_RTHG }
- ,{" SMD ", Ins_SMD }
- ,{" ELSE ", Ins_ELSE }
- ,{" JMPR ", Ins_JMPR }
- ,{" SCvTCi ", Ins_SCVTCI }
- ,{" SSwCi ", Ins_SSWCI }
- ,{" SSW ", Ins_SSW }
- ,{" DUP ", Ins_DUP }
- ,{" POP ", Ins_POP }
- ,{" CLEAR ", Ins_CLEAR }
- ,{" SWAP ", Ins_SWAP }
- ,{" DEPTH ", Ins_DEPTH }
- ,{" CINDEX ", Ins_CINDEX }
- ,{" MINDEX ", Ins_MINDEX }
- ,{" AlignPTS ", Ins_ALIGNPTS}
- ,{" INS_$28 ", Ins_UNKNOWN }
- ,{" UTP ", Ins_UTP }
- ,{" LOOPCALL ", Ins_LOOPCALL}
- ,{" CALL ", Ins_CALL }
- ,{" FDEF ", Ins_FDEF }
- ,{" ENDF ", Ins_ENDF }
- ,{" MDAP[0] ", Ins_MDAP }
- ,{" MDAP[1] ", Ins_MDAP }
- ,{" IUP[0] ", Ins_IUP }
- ,{" IUP[1] ", Ins_IUP }
- ,{" SHP[0] ", Ins_SHP }
- ,{" SHP[1] ", Ins_SHP }
- ,{" SHC[0] ", Ins_SHC }
- ,{" SHC[1] ", Ins_SHC }
- ,{" SHZ[0] ", Ins_SHZ }
- ,{" SHZ[1] ", Ins_SHZ }
- ,{" SHPIX ", Ins_SHPIX }
- ,{" IP ", Ins_IP }
- ,{" MSIRP[0] ", Ins_MSIRP }
- ,{" MSIRP[1] ", Ins_MSIRP }
- ,{" AlignRP ", Ins_ALIGNRP }
- ,{" RTDG ", Ins_RTDG }
- ,{" MIAP[0] ", Ins_MIAP }
- ,{" MIAP[1] ", Ins_MIAP }
- ,{" NPushB ", Ins_NPUSHB }
- ,{" NPushW ", Ins_NPUSHW }
- ,{" WS ", Ins_WS }
- ,{" RS ", Ins_RS }
- ,{" WCvtP ", Ins_WCVTP }
- ,{" RCvt ", Ins_RCVT }
- ,{" GC[0] ", Ins_GC }
- ,{" GC[1] ", Ins_GC }
- ,{" SCFS ", Ins_SCFS }
- ,{" MD[0] ", Ins_MD }
- ,{" MD[1] ", Ins_MD }
- ,{" MPPEM ", Ins_MPPEM }
- ,{" MPS ", Ins_MPS }
- ,{" FlipON ", Ins_FLIPON }
- ,{" FlipOFF ", Ins_FLIPOFF }
- ,{" DEBUG ", Ins_DEBUG }
- ,{" LT ", Ins_LT }
- ,{" LTEQ ", Ins_LTEQ }
- ,{" GT ", Ins_GT }
- ,{" GTEQ ", Ins_GTEQ }
- ,{" EQ ", Ins_EQ }
- ,{" NEQ ", Ins_NEQ }
- ,{" ODD ", Ins_ODD }
- ,{" EVEN ", Ins_EVEN }
- ,{" IF ", Ins_IF }
- ,{" EIF ", Ins_EIF }
- ,{" AND ", Ins_AND }
- ,{" OR ", Ins_OR }
- ,{" NOT ", Ins_NOT }
- ,{" DeltaP1 ", Ins_DELTAP }
- ,{" SDB ", Ins_SDB }
- ,{" SDS ", Ins_SDS }
- ,{" ADD ", Ins_ADD }
- ,{" SUB ", Ins_SUB }
- ,{" DIV ", Ins_DIV }
- ,{" MUL ", Ins_MUL }
- ,{" ABS ", Ins_ABS }
- ,{" NEG ", Ins_NEG }
- ,{" FLOOR ", Ins_FLOOR }
- ,{" CEILING ", Ins_CEILING }
- ,{" ROUND[0] ", Ins_ROUND }
- ,{" ROUND[1] ", Ins_ROUND }
- ,{" ROUND[2] ", Ins_ROUND }
- ,{" ROUND[3] ", Ins_ROUND }
- ,{" NROUND[0] ", Ins_NROUND }
- ,{" NROUND[1] ", Ins_NROUND }
- ,{" NROUND[2] ", Ins_NROUND }
- ,{" NROUND[3] ", Ins_NROUND }
- ,{" WCvtF ", Ins_WCVTF }
- ,{" DeltaP2 ", Ins_DELTAP }
- ,{" DeltaP3 ", Ins_DELTAP }
- ,{" DeltaCn[0] ", Ins_DELTAC }
- ,{" DeltaCn[1] ", Ins_DELTAC }
- ,{" DeltaCn[2] ", Ins_DELTAC }
- ,{" SROUND ", Ins_SROUND }
- ,{" S45Round ", Ins_S45ROUND }
- ,{" JROT ", Ins_JROT }
- ,{" JROF ", Ins_JROF }
- ,{" ROFF ", Ins_ROFF }
- ,{" INS_$7B ", Ins_UNKNOWN }
- ,{" RUTG ", Ins_RUTG }
- ,{" RDTG ", Ins_RDTG }
- ,{" SANGW ", Ins_SANGW }
- ,{" AA ", Ins_AA }
- ,{" FlipPT ", Ins_FLIPPT }
- ,{" FlipRgON ", Ins_FLIPRGON }
- ,{" FlipRgOFF ", Ins_FLIPRGOFF }
- ,{" INS_$83 ", Ins_UNKNOWN }
- ,{" INS_$84 ", Ins_UNKNOWN }
- ,{" ScanCTRL ", Ins_SCANCTRL }
- ,{" SDPVTL[0] ", Ins_SDPVTL }
- ,{" SDPVTL[1] ", Ins_SDPVTL }
- ,{" GetINFO ", Ins_GETINFO }
- ,{" IDEF ", Ins_IDEF }
- ,{" ROLL ", Ins_ROLL }
- ,{" MAX ", Ins_MAX }
- ,{" MIN ", Ins_MIN }
- ,{" ScanTYPE ", Ins_SCANTYPE }
- ,{" InstCTRL ", Ins_INSTCTRL }
- ,{" INS_$8F ", Ins_UNKNOWN }
- ,{" INS_$90 ", Ins_UNKNOWN }
- ,{" INS_$91 ", Ins_UNKNOWN }
- ,{" INS_$92 ", Ins_UNKNOWN }
- ,{" INS_$93 ", Ins_UNKNOWN }
- ,{" INS_$94 ", Ins_UNKNOWN }
- ,{" INS_$95 ", Ins_UNKNOWN }
- ,{" INS_$96 ", Ins_UNKNOWN }
- ,{" INS_$97 ", Ins_UNKNOWN }
- ,{" INS_$98 ", Ins_UNKNOWN }
- ,{" INS_$99 ", Ins_UNKNOWN }
- ,{" INS_$9A ", Ins_UNKNOWN }
- ,{" INS_$9B ", Ins_UNKNOWN }
- ,{" INS_$9C ", Ins_UNKNOWN }
- ,{" INS_$9D ", Ins_UNKNOWN }
- ,{" INS_$9E ", Ins_UNKNOWN }
- ,{" INS_$9F ", Ins_UNKNOWN }
- ,{" INS_$A0 ", Ins_UNKNOWN }
- ,{" INS_$A1 ", Ins_UNKNOWN }
- ,{" INS_$A2 ", Ins_UNKNOWN }
- ,{" INS_$A3 ", Ins_UNKNOWN }
- ,{" INS_$A4 ", Ins_UNKNOWN }
- ,{" INS_$A5 ", Ins_UNKNOWN }
- ,{" INS_$A6 ", Ins_UNKNOWN }
- ,{" INS_$A7 ", Ins_UNKNOWN }
- ,{" INS_$A8 ", Ins_UNKNOWN }
- ,{" INS_$A9 ", Ins_UNKNOWN }
- ,{" INS_$AA ", Ins_UNKNOWN }
- ,{" INS_$AB ", Ins_UNKNOWN }
- ,{" INS_$AC ", Ins_UNKNOWN }
- ,{" INS_$AD ", Ins_UNKNOWN }
- ,{" INS_$AE ", Ins_UNKNOWN }
- ,{" INS_$AF ", Ins_UNKNOWN }
- ,{" PushB[0] ", Ins_PUSHB }
- ,{" PushB[1] ", Ins_PUSHB }
- ,{" PushB[2] ", Ins_PUSHB }
- ,{" PushB[3] ", Ins_PUSHB }
- ,{" PushB[4] ", Ins_PUSHB }
- ,{" PushB[5] ", Ins_PUSHB }
- ,{" PushB[6] ", Ins_PUSHB }
- ,{" PushB[7] ", Ins_PUSHB }
- ,{" PushW[0] ", Ins_PUSHW }
- ,{" PushW[1] ", Ins_PUSHW }
- ,{" PushW[2] ", Ins_PUSHW }
- ,{" PushW[3] ", Ins_PUSHW }
- ,{" PushW[4] ", Ins_PUSHW }
- ,{" PushW[5] ", Ins_PUSHW }
- ,{" PushW[6] ", Ins_PUSHW }
- ,{" PushW[7] ", Ins_PUSHW }
- ,{" MDRP[00] ", Ins_MDRP }
- ,{" MDRP[01] ", Ins_MDRP }
- ,{" MDRP[02] ", Ins_MDRP }
- ,{" MDRP[03] ", Ins_MDRP }
- ,{" MDRP[04] ", Ins_MDRP }
- ,{" MDRP[05] ", Ins_MDRP }
- ,{" MDRP[06] ", Ins_MDRP }
- ,{" MDRP[07] ", Ins_MDRP }
- ,{" MDRP[08] ", Ins_MDRP }
- ,{" MDRP[09] ", Ins_MDRP }
- ,{" MDRP[10] ", Ins_MDRP }
- ,{" MDRP[11] ", Ins_MDRP }
- ,{" MDRP[12] ", Ins_MDRP }
- ,{" MDRP[13] ", Ins_MDRP }
- ,{" MDRP[14] ", Ins_MDRP }
- ,{" MDRP[15] ", Ins_MDRP }
- ,{" MDRP[16] ", Ins_MDRP }
- ,{" MDRP[17] ", Ins_MDRP }
- ,{" MDRP[18] ", Ins_MDRP }
- ,{" MDRP[19] ", Ins_MDRP }
- ,{" MDRP[20] ", Ins_MDRP }
- ,{" MDRP[21] ", Ins_MDRP }
- ,{" MDRP[22] ", Ins_MDRP }
- ,{" MDRP[23] ", Ins_MDRP }
- ,{" MDRP[24] ", Ins_MDRP }
- ,{" MDRP[25] ", Ins_MDRP }
- ,{" MDRP[26] ", Ins_MDRP }
- ,{" MDRP[27] ", Ins_MDRP }
- ,{" MDRP[28] ", Ins_MDRP }
- ,{" MDRP[29] ", Ins_MDRP }
- ,{" MDRP[30] ", Ins_MDRP }
- ,{" MDRP[31] ", Ins_MDRP }
- ,{" MIRP[00] ", Ins_MIRP }
- ,{" MIRP[01] ", Ins_MIRP }
- ,{" MIRP[02] ", Ins_MIRP }
- ,{" MIRP[03] ", Ins_MIRP }
- ,{" MIRP[04] ", Ins_MIRP }
- ,{" MIRP[05] ", Ins_MIRP }
- ,{" MIRP[06] ", Ins_MIRP }
- ,{" MIRP[07] ", Ins_MIRP }
- ,{" MIRP[08] ", Ins_MIRP }
- ,{" MIRP[09] ", Ins_MIRP }
- ,{" MIRP[10] ", Ins_MIRP }
- ,{" MIRP[11] ", Ins_MIRP }
- ,{" MIRP[12] ", Ins_MIRP }
- ,{" MIRP[13] ", Ins_MIRP }
- ,{" MIRP[14] ", Ins_MIRP }
- ,{" MIRP[15] ", Ins_MIRP }
- ,{" MIRP[16] ", Ins_MIRP }
- ,{" MIRP[17] ", Ins_MIRP }
- ,{" MIRP[18] ", Ins_MIRP }
- ,{" MIRP[19] ", Ins_MIRP }
- ,{" MIRP[20] ", Ins_MIRP }
- ,{" MIRP[21] ", Ins_MIRP }
- ,{" MIRP[22] ", Ins_MIRP }
- ,{" MIRP[23] ", Ins_MIRP }
- ,{" MIRP[24] ", Ins_MIRP }
- ,{" MIRP[25] ", Ins_MIRP }
- ,{" MIRP[26] ", Ins_MIRP }
- ,{" MIRP[27] ", Ins_MIRP }
- ,{" MIRP[28] ", Ins_MIRP }
- ,{" MIRP[29] ", Ins_MIRP }
- ,{" MIRP[30] ", Ins_MIRP }
- ,{" MIRP[31] ", Ins_MIRP }
- };
- /****************************************************************/
- /* */
- /* RUN */
- /* */
- /* This function executes a run of opcodes. It will exit */
- /* in the following cases: */
- /* */
- /* - Errors (in which case it returns FALSE) */
- /* */
- /* - Reaching the end of the main code range (returns TRUE). */
- /* Reaching the end of a code range within a function */
- /* call is an error. */
- /* */
- /* - After executing one single opcode, if the flag */
- /* 'Instruction_Trap' is set to TRUE (returns TRUE). */
- /* */
- /* On exit whith TRUE, test IP < CodeSize to know wether it */
- /* comes from a instruction trap or a normal termination. */
- /* */
- /* */
- /* Note: The documented DEBUG opcode pops a value from */
- /* the stack. This behaviour is unsupported, here */
- /* a DEBUG opcode is always an error. */
- /* */
- /* */
- /* THIS IS THE INTERPRETER'S MAIN LOOP */
- /* */
- /* Instructions appear in the specs' order. */
- /* */
- /****************************************************************/
- TT_Error RunIns( PExecution_Context exc )
- {
- TT_Error Result;
- Int A;
- PDefRecord WITH;
- PCallRecord WITH1;
- bool bFirst;
- bool dbg_prt = (DBG_PRT_FUN != NULL);
- # ifdef DEBUG
- ttfMemory *mem = exc->current_face->font->tti->ttf_memory;
- F26Dot6 *save_ox, *save_oy, *save_cx, *save_cy;
- DBG_PRINT("\n%% *** Entering RunIns ***");
- # endif
- /* set CVT functions */
- CUR.metrics.ratio = 0;
- if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
- {
- /* non-square pixels, use the stretched routines */
- CUR.func_read_cvt = Read_CVT_Stretched;
- CUR.func_write_cvt = Write_CVT_Stretched;
- CUR.func_move_cvt = Move_CVT_Stretched;
- }
- else
- {
- /* square pixels, use normal routines */
- CUR.func_read_cvt = Read_CVT;
- CUR.func_write_cvt = Write_CVT;
- CUR.func_move_cvt = Move_CVT;
- }
- COMPUTE_Funcs();
- Compute_Round( EXEC_ARGS (Byte)exc->GS.round_state );
- # ifdef DEBUG
- if (dbg_prt && CUR.pts.n_points) {
- save_ox = mem->alloc_bytes(mem, CUR.pts.n_points * sizeof(*save_ox), "RunIns");
- save_oy = mem->alloc_bytes(mem, CUR.pts.n_points * sizeof(*save_oy), "RunIns");
- save_cx = mem->alloc_bytes(mem, CUR.pts.n_points * sizeof(*save_cx), "RunIns");
- save_cy = mem->alloc_bytes(mem, CUR.pts.n_points * sizeof(*save_cy), "RunIns");
- if (!save_ox || !save_oy || !save_cx || !save_cy)
- return TT_Err_Out_Of_Memory;
- } else
- save_ox = save_oy = save_cx = save_cy = NULL;
- # endif
- Result = setjmp(exc->trap);
- if (Result) {
- CUR.error = Result;
- goto _LExit;
- }
- bFirst = true;
- do
- {
- CALC_Length();
- /* First, let's check for empty stack and overflow */
- CUR.args = CUR.top - Pop_Push_Count[CUR.opcode * 2];
- /* `args' is the top of the stack once arguments have been popped. */
- /* One can also interpret it as the index of the last argument. */
- if ( CUR.args < 0 )
- {
- CUR.error = TT_Err_Too_Few_Arguments;
- goto _LErrorLabel;
- }
- CUR.new_top = CUR.args + Pop_Push_Count[CUR.opcode * 2 + 1];
- /* `new_top' is the new top of the stack, after the instruction's */
- /* execution. `top' will be set to `new_top' after the 'switch' */
- /* statement. */
- if ( CUR.new_top > CUR.stackSize )
- {
- CUR.error = TT_Err_Stack_Overflow;
- goto _LErrorLabel;
- }
- CUR.step_ins = TRUE;
- CUR.error = TT_Err_Ok;
- # ifdef DEBUG
- DBG_PRINT3("\n%%n=%5d IP=%5d OP=%s ", nInstrCount, CUR.IP, Instruct_Dispatch[CUR.opcode].sName);
- /*
- { for(int i=0;i<CUR.top;i++)
- DBG_PRINT1("% %d",CUR.stack[i]);
- }
- */
- if (save_ox != NULL) {
- memcpy(save_ox, CUR.pts.org_x, sizeof(CUR.pts.org_x[0]) * CUR.pts.n_points);
- memcpy(save_oy, CUR.pts.org_y, sizeof(CUR.pts.org_y[0]) * CUR.pts.n_points);
- memcpy(save_cx, CUR.pts.cur_x, sizeof(CUR.pts.cur_x[0]) * CUR.pts.n_points);
- memcpy(save_cy, CUR.pts.cur_y, sizeof(CUR.pts.cur_y[0]) * CUR.pts.n_points);
- }
- # endif
- Instruct_Dispatch[CUR.opcode].p( EXEC_ARGS &CUR.stack[CUR.args] );
- # ifdef DEBUG
- if (save_ox != NULL) {
- F26Dot6 *pp[4], *qq[4];
- const char *ss[] = {"org.x", "org.y", "cur.x", "cur.y"};
- int l = 0, i, j;
- pp[0] = save_ox,
- pp[1] = save_oy,
- pp[2] = save_cx,
- pp[3] = save_cy;
- qq[0] = CUR.pts.org_x;
- qq[1] = CUR.pts.org_y;
- qq[2] = CUR.pts.cur_x;
- qq[3] = CUR.pts.cur_y;
- for(i = 0; i < 4; i++)
- for(j = 0;j < CUR.pts.n_points; j++)
- { F26Dot6 *ppi = pp[i], *qqi = qq[i];
- if(ppi[j] != qqi[j] || bFirst)
- {
- DBG_PRINT4("%% %s[%d]%d:=%d", ss[i], j, pp[i][j], qq[i][j]);
- if(++l > 3)
- { l=0;
- DBG_PRINT("\n");
- }
- }
- }
- nInstrCount++;
- bFirst=FALSE;
- }
- # endif
- DBG_PAINT
- if ( CUR.error != TT_Err_Ok )
- {
- switch ( CUR.error )
- {
- case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
- A = 0;
- while ( A < CUR.numIDefs )
- {
- WITH = &CUR.IDefs[A];
- if ( WITH->Active && CUR.opcode == WITH->Opc )
- {
- if ( CUR.callTop >= CUR.callSize )
- {
- CUR.error = TT_Err_Invalid_Reference;
- goto _LErrorLabel;
- }
- WITH1 = &CUR.callStack[CUR.callTop];
- WITH1->Caller_Range = CUR.curRange;
- WITH1->Caller_IP = CUR.IP + 1;
- WITH1->Cur_Count = 1;
- WITH1->Cur_Restart = WITH->Start;
- if ( INS_Goto_CodeRange( WITH->Range, WITH->Start ) == FAILURE )
- goto _LErrorLabel;
- goto _LSuiteLabel;
- }
- else
- {
- A++;
- continue;
- }
- }
- CUR.error = TT_Err_Invalid_Opcode;
- goto _LErrorLabel;
- break;
- default:
- CUR.error = CUR.error;
- goto _LErrorLabel;
- break;
- }
- }
- CUR.top = CUR.new_top;
- if ( CUR.step_ins )
- CUR.IP += CUR.length;
- _LSuiteLabel:
- if ( CUR.IP >= CUR.codeSize )
- {
- if ( CUR.callTop > 0 )
- {
- CUR.error = TT_Err_Code_Overflow;
- goto _LErrorLabel;
- }
- else
- goto _LNo_Error;
- }
- } while ( !CUR.instruction_trap );
- _LNo_Error:
- Result = TT_Err_Ok;
- goto _LExit;
- _LErrorLabel:
- Result = CUR.error;
- DBG_PRINT1("%% ERROR=%d", Result);
- _LExit:
- # ifdef DEBUG
- if (save_ox != NULL) {
- mem->free(mem, save_ox, "RunIns");
- mem->free(mem, save_oy, "RunIns");
- mem->free(mem, save_cx, "RunIns");
- mem->free(mem, save_cy, "RunIns");
- }
- # endif
- return Result;
- }
|